Skip to content

Commit 2b73cf0

Browse files
committed
implement intoiterator for lookup
1 parent 1fe8c04 commit 2b73cf0

File tree

3 files changed

+39
-37
lines changed

3 files changed

+39
-37
lines changed

src/gadgets/lookup.rs

+15-12
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
//! This module implements lookup gadget for applications built with Nova.
22
use std::cmp::max;
3+
use std::collections::btree_map::Iter;
34
use std::collections::BTreeMap;
5+
use std::collections::btree_map::Values;
46

57
use bellpepper_core::{num::AllocatedNum, ConstraintSystem, LinearCombination, SynthesisError};
68
use std::cmp::Ord;
@@ -508,7 +510,7 @@ impl<'a, G: Group> LookupTraceBuilder<'a, G> {
508510
/// Lookup in R1CS
509511
#[derive(Clone, Debug)]
510512
pub struct Lookup<F: PrimeField> {
511-
pub(crate) map_aux: BTreeMap<F, (F, F)>, // (value, counter)
513+
map_aux: BTreeMap<F, (F, F)>, // (value, counter)
512514
rw_counter: F,
513515
pub(crate) table_type: TableType, // read only or read-write
514516
pub(crate) max_cap_rwcounter_log2: usize, // max cap for rw_counter operation in bits
@@ -536,21 +538,15 @@ impl<F: PrimeField> Lookup<F> {
536538
}
537539
}
538540

539-
/// get table vector
540-
/// very costly operation
541-
pub fn get_table(&self) -> Vec<(F, F, F)> {
542-
self
543-
.map_aux
544-
.iter()
545-
.map(|(addr, (value, counter))| (*addr, *value, *counter))
546-
.collect()
547-
}
548-
549541
/// table size
550542
pub fn table_size(&self) -> usize {
551543
self.map_aux.len()
552544
}
553545

546+
pub fn values(&self) -> Values<'_, F, (F, F)> {
547+
self.map_aux.values()
548+
}
549+
554550
fn rw_operation(&mut self, addr: F, external_value: Option<F>) -> (F, F)
555551
where
556552
F: Ord,
@@ -577,8 +573,15 @@ impl<F: PrimeField> Lookup<F> {
577573
self.rw_counter = write_counter;
578574
(read_value, read_counter)
579575
}
576+
}
580577

581-
// fn write(&mut self, addr: AllocatedNum<F>, value: F) {}
578+
impl<'a, F: PrimeField> IntoIterator for &'a Lookup<F> {
579+
type Item = (&'a F, &'a (F, F));
580+
type IntoIter = Iter<'a, F, (F, F)>;
581+
582+
fn into_iter(self) -> Self::IntoIter {
583+
self.map_aux.iter()
584+
}
582585
}
583586

584587
/// c = a + b where a, b is AllocatedNum

src/lib.rs

+5-8
Original file line numberDiff line numberDiff line change
@@ -1719,11 +1719,10 @@ mod tests {
17191719
G2: Group<Base = <G1 as Group>::Scalar>,
17201720
{
17211721
fn new(
1722-
initial_table: &Lookup<G1::Scalar>,
1722+
initial_table: Lookup<G1::Scalar>,
17231723
ro_consts_circuit: ROConstantsCircuit<G2>,
17241724
) -> (Vec<Self>, Lookup<G1::Scalar>, G1::Scalar) {
17251725
let n = initial_table.table_size();
1726-
let initial_table = initial_table.clone();
17271726

17281727
let initial_index = (n - 4) / 2;
17291728
let max_value_bits = (n - 1).log_2() + 1; // + 1 as a buffer
@@ -1985,7 +1984,7 @@ mod tests {
19851984
};
19861985

19871986
let (circuit_primaries, final_table, expected_intermediate_gamma) =
1988-
HeapifyCircuit::new(&initial_table, ro_consts);
1987+
HeapifyCircuit::new(initial_table.clone(), ro_consts);
19891988

19901989
let circuit_secondary = TrivialCircuit::default();
19911990

@@ -2076,17 +2075,15 @@ mod tests {
20762075
);
20772076

20782077
// lookup snark prove/verify
2079-
// type EE = crate::provider::ipa_pc::EvaluationEngine<G1>;
2080-
let (pk, vk) =
2081-
LookupSNARK::<G1, EE<_>>::setup(&pp.ck_primary, &initial_table.get_table()).unwrap();
2078+
let (pk, vk) = LookupSNARK::<G1, EE<_>>::setup(&pp.ck_primary, &initial_table).unwrap();
20822079
let snark_proof = LookupSNARK::<G1, EE<_>>::prove(
20832080
&pp.ck_primary,
20842081
&pk,
20852082
(alpha, gamma),
20862083
read_row,
20872084
write_row,
2088-
initial_table.get_table(),
2089-
final_table.get_table(),
2085+
&initial_table,
2086+
&final_table,
20902087
)
20912088
.unwrap();
20922089

src/spartan/lookupsnark.rs

+19-17
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use crate::{
33
constants::NUM_CHALLENGE_BITS,
44
digest::{DigestComputer, SimpleDigestible},
55
errors::NovaError,
6-
gadgets::utils::scalar_as_base,
6+
gadgets::{lookup::Lookup, utils::scalar_as_base},
77
spartan::{
88
math::Math,
99
polys::{
@@ -120,17 +120,19 @@ where
120120
/// setup
121121
pub fn setup(
122122
ck: &CommitmentKey<G>,
123-
initial_table: &Vec<(G::Scalar, G::Scalar, G::Scalar)>,
123+
initial_table: &Lookup<G::Scalar>,
124124
) -> Result<(ProverKey<G, EE>, VerifierKey<G, EE>), NovaError> {
125125
// check the provided commitment key meets minimal requirements
126126
// assert!(ck.length() >= Self::commitment_key_floor()(S));
127-
let init_values: Vec<<G as Group>::Scalar> =
128-
initial_table.iter().map(|(_, value, _)| *value).collect();
127+
let init_values: Vec<<G as Group>::Scalar> = initial_table
128+
.into_iter()
129+
.map(|(_, (value, _))| *value)
130+
.collect();
129131

130132
let comm_init_value = G::CE::commit(ck, &init_values);
131133

132134
let (pk_ee, vk_ee) = EE::setup(ck);
133-
let table_size = initial_table.len();
135+
let table_size = initial_table.table_size();
134136

135137
let vk = VerifierKey::new(vk_ee, table_size, comm_init_value);
136138

@@ -150,8 +152,8 @@ where
150152
challenges: (G::Scalar, G::Scalar),
151153
read_row: G::Scalar,
152154
write_row: G::Scalar,
153-
initial_table: Vec<(G::Scalar, G::Scalar, G::Scalar)>,
154-
final_table: Vec<(G::Scalar, G::Scalar, G::Scalar)>,
155+
initial_table: &Lookup<G::Scalar>,
156+
final_table: &Lookup<G::Scalar>,
155157
) -> Result<Self, NovaError> {
156158
// a list of polynomial evaluation claims that will be batched
157159
let mut w_u_vec = Vec::new();
@@ -163,13 +165,13 @@ where
163165
};
164166
// init_row
165167
let initial_row: Vec<G::Scalar> = initial_table
166-
.iter()
167-
.map(|(addr, value, counter)| hash_func(addr, value, counter))
168+
.into_iter()
169+
.map(|(addr, (value, counter))| hash_func(addr, value, counter))
168170
.collect();
169171
// audit_row
170172
let audit_row: Vec<G::Scalar> = final_table
171-
.iter()
172-
.map(|(addr, value, counter)| hash_func(addr, value, counter))
173+
.into_iter()
174+
.map(|(addr, (value, counter))| hash_func(addr, value, counter))
173175
.collect();
174176
let mut transcript = G::TE::new(b"LookupSNARK");
175177
// append the verifier key (which includes commitment to R1CS matrices) and the read_row/write_row to the transcript
@@ -179,12 +181,12 @@ where
179181
transcript.absorb(b"alpha", &fingerprint_alpha);
180182
transcript.absorb(b"gamma", &fingerprint_gamma);
181183

182-
let init_values: Vec<<G as Group>::Scalar> =
183-
initial_table.iter().map(|(_, value, _)| *value).collect();
184-
let final_values: Vec<<G as Group>::Scalar> =
185-
final_table.iter().map(|(_, value, _)| *value).collect();
186-
let final_counters: Vec<<G as Group>::Scalar> =
187-
final_table.iter().map(|(_, _, counter)| *counter).collect();
184+
let init_values: Vec<<G as Group>::Scalar> = initial_table
185+
.into_iter()
186+
.map(|(_, (value, _))| *value)
187+
.collect();
188+
let (final_values, final_counters): (Vec<_>, Vec<_>) =
189+
final_table.values().copied().unzip();
188190
let comm_init_value = pk.comm_init_value;
189191
let (comm_final_value, comm_final_counter) = rayon::join(
190192
|| G::CE::commit(ck, &final_values),

0 commit comments

Comments
 (0)