From a5101fd019d9b7800f62e865008e67acdf7310e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Garillot?= <4142+huitseeker@users.noreply.github.com> Date: Tue, 26 Sep 2023 15:44:54 -0400 Subject: [PATCH] [PoC] feat: moving to shared store references (#680) * chore: Replace CacheMap with Elsa's FrozenMap - Removed the `src/cache_map.rs` file and `cache_map` module from the codebase. - Replaced the use of `CacheMap` with `FrozenMap` from the `elsa` crate in the `PoseidonCache` and `Store` structures across multiple files. - Added `elsa` dependency, version `1.9.0`, with `indexmap` feature to the `Cargo.toml` file. - `CacheMap` imports throughout the codebase have been removed and replaced with imports of `elsa::sync::FrozenMap`. * refactor: use elsa::sync_index_set::FrozenIndexSet * fix: remove uneeded mutable references to the store * refactor: convert store HashMap to FrozenMap * fix: remove a few uneeded references * fix: adapt hydration to not require &mut * fix: remove uneeded mutability modifiers - Removed mutability modifier from `store` variable * refactor: Refactor code to replace mutable Store references with immutable ones * adapt LEM infra * Removed exclusive reference to `hydrate_z_cache` in LEM * more LEM simplifications * fix: speed up hydration * eliminate 'cloned' call on hydration; recover parallel hydration on LEM store --------- Co-authored-by: Arthur Paulino Co-authored-by: Gabriel Barreto --- Cargo.toml | 2 + benches/end2end.rs | 4 +- benches/sha256_ivc.rs | 2 +- examples/circom.rs | 2 +- examples/sha256.rs | 2 +- examples/sha256_ivc.rs | 2 +- examples/sha256_nivc.rs | 2 +- lurk-macros/src/lib.rs | 4 +- src/cache_map.rs | 340 ------------------------------ src/circuit/circuit_frame.rs | 12 +- src/circuit/gadgets/circom/mod.rs | 2 +- src/cli/commitment.rs | 2 +- src/cli/repl.rs | 14 +- src/cont.rs | 54 +++-- src/coprocessor/circom.rs | 2 +- src/coprocessor/mod.rs | 6 +- src/coprocessor/trie/mod.rs | 20 +- src/eval/lang.rs | 11 +- src/eval/mod.rs | 22 +- src/eval/reduction.rs | 24 +-- src/eval/tests/mod.rs | 16 +- src/hash.rs | 27 ++- src/hash_witness.rs | 22 +- src/lem/circuit.rs | 13 +- src/lem/eval.rs | 18 +- src/lem/interpreter.rs | 8 +- src/lem/mod.rs | 20 +- src/lem/store.rs | 137 ++++++------ src/lem/zstore.rs | 2 +- src/lib.rs | 3 - src/proof/groth16.rs | 4 +- src/proof/nova.rs | 2 +- src/repl.rs | 2 +- src/store.rs | 336 +++++++++++++++-------------- src/syntax.rs | 2 +- src/writer.rs | 2 +- src/z_data/z_store.rs | 2 +- 37 files changed, 388 insertions(+), 757 deletions(-) delete mode 100644 src/cache_map.rs diff --git a/Cargo.toml b/Cargo.toml index a23c88b585..8e23ffbc10 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -68,6 +68,8 @@ ansi_term = "0.12.1" tracing = { workspace = true } tracing-texray = { workspace = true } tracing-subscriber = { workspace = true, features = ["env-filter"] } +elsa = { version = "1.9.0", git="https://github.com/lurk-lab/elsa", branch = "sync_index_map", features = ["indexmap"] } +arc-swap = "1.6.0" [target.'cfg(not(target_arch = "wasm32"))'.dependencies] memmap = { version = "0.5.10", package = "memmap2" } diff --git a/benches/end2end.rs b/benches/end2end.rs index eb8572b06c..13fe31dfba 100644 --- a/benches/end2end.rs +++ b/benches/end2end.rs @@ -203,7 +203,7 @@ fn eval_benchmark(c: &mut Criterion) { Evaluator::new( ptr, empty_sym_env(&bls12_store), - &mut bls12_store, + &bls12_store, limit, &lang_bls12, ) @@ -220,7 +220,7 @@ fn eval_benchmark(c: &mut Criterion) { Evaluator::new( ptr, empty_sym_env(&pallas_store), - &mut pallas_store, + &pallas_store, limit, &lang_pallas, ) diff --git a/benches/sha256_ivc.rs b/benches/sha256_ivc.rs index 65968874d5..2f47147c0f 100644 --- a/benches/sha256_ivc.rs +++ b/benches/sha256_ivc.rs @@ -139,7 +139,7 @@ impl Coprocessor for Sha256Coprocessor { self.arity } - fn simple_evaluate(&self, s: &mut Store, args: &[Ptr]) -> Ptr { + fn simple_evaluate(&self, s: &Store, args: &[Ptr]) -> Ptr { let mut hasher = ::new(); let mut input = vec![0u8; 64 * self.arity]; diff --git a/examples/circom.rs b/examples/circom.rs index 74b8ab477e..199fd468b4 100644 --- a/examples/circom.rs +++ b/examples/circom.rs @@ -77,7 +77,7 @@ impl CircomGadget for CircomSha256 { vec![a, b] } - fn simple_evaluate(&self, s: &mut Store, _args: &[Ptr]) -> Ptr { + fn simple_evaluate(&self, s: &Store, _args: &[Ptr]) -> Ptr { // TODO: actually use the lurk inputs let expected = Num::Scalar( F::from_str_vartime( diff --git a/examples/sha256.rs b/examples/sha256.rs index 52bf2d1667..8804ead50f 100644 --- a/examples/sha256.rs +++ b/examples/sha256.rs @@ -111,7 +111,7 @@ impl Coprocessor for Sha256Coprocessor { 0 } - fn simple_evaluate(&self, s: &mut Store, _args: &[Ptr]) -> Ptr { + fn simple_evaluate(&self, s: &Store, _args: &[Ptr]) -> Ptr { let mut hasher = Sha256::new(); let input = vec![0u8; self.n]; diff --git a/examples/sha256_ivc.rs b/examples/sha256_ivc.rs index 1edf391512..082589deb0 100644 --- a/examples/sha256_ivc.rs +++ b/examples/sha256_ivc.rs @@ -122,7 +122,7 @@ impl Coprocessor for Sha256Coprocessor { self.n } - fn simple_evaluate(&self, s: &mut Store, args: &[Ptr]) -> Ptr { + fn simple_evaluate(&self, s: &Store, args: &[Ptr]) -> Ptr { let mut hasher = Sha256::new(); let mut input = vec![0u8; 64 * self.n]; diff --git a/examples/sha256_nivc.rs b/examples/sha256_nivc.rs index 2ed65c01ea..683303d5cc 100644 --- a/examples/sha256_nivc.rs +++ b/examples/sha256_nivc.rs @@ -113,7 +113,7 @@ impl Coprocessor for Sha256Coprocessor { 1 } - fn simple_evaluate(&self, s: &mut Store, args: &[Ptr]) -> Ptr { + fn simple_evaluate(&self, s: &Store, args: &[Ptr]) -> Ptr { let mut hasher = Sha256::new(); let mut input = vec![0u8; 64]; diff --git a/lurk-macros/src/lib.rs b/lurk-macros/src/lib.rs index 15fe0d52b8..a8e5afb8eb 100644 --- a/lurk-macros/src/lib.rs +++ b/lurk-macros/src/lib.rs @@ -50,13 +50,13 @@ fn impl_enum_coproc(name: &Ident, variants: &DataEnum) -> TokenStream { } } - fn evaluate(&self, s: &mut lurk::store::Store, args: lurk::ptr::Ptr, env: lurk::ptr::Ptr, cont: lurk::ptr::ContPtr) -> lurk::eval::IO { + fn evaluate(&self, s: &lurk::store::Store, args: lurk::ptr::Ptr, env: lurk::ptr::Ptr, cont: lurk::ptr::ContPtr) -> lurk::eval::IO { match self { #evaluate_arms } } - fn simple_evaluate(&self, s: &mut lurk::store::Store, args: &[lurk::ptr::Ptr]) -> lurk::ptr::Ptr { + fn simple_evaluate(&self, s: &lurk::store::Store, args: &[lurk::ptr::Ptr]) -> lurk::ptr::Ptr { match self { #simple_evaluate_arms } diff --git a/src/cache_map.rs b/src/cache_map.rs deleted file mode 100644 index a40e11779d..0000000000 --- a/src/cache_map.rs +++ /dev/null @@ -1,340 +0,0 @@ -use stable_deref_trait::StableDeref; -use std::borrow::Borrow; -use std::collections::HashMap; -use std::hash::Hash; - -use std::sync::RwLock; - -#[derive(Debug)] -/// `CacheMap` is an adaptation of `FrozenMap`: -/// `` -pub struct CacheMap { - map: RwLock>, -} - -impl Default for CacheMap { - fn default() -> Self { - Self { - map: Default::default(), - } - } -} - -impl CacheMap { - pub fn new() -> Self { - Self::default() - } -} - -impl CacheMap { - // these should never return &K or &V - // these should never delete any entries - - /// If the key exists in the map, returns a reference - /// to the corresponding value, otherwise inserts a - /// new entry in the map for that key and returns a - /// reference to the given value. - /// - /// Existing values are never overwritten. - /// - /// The key may be any borrowed form of the map's key type, but - /// [`Hash`] and [`Eq`] on the borrowed form *must* match those for - /// the key type. - /// - /// # Examples - /// - /// ``` - /// use lurk::cache_map::CacheMap; - /// - /// let map = CacheMap::new(); - /// assert_eq!(map.insert(1, Box::new("a")), &"a"); - /// assert_eq!(map.insert(1, Box::new("b")), &"a"); - /// ``` - pub fn insert(&self, k: K, v: V) -> &V::Target { - let mut map = self.map.write().unwrap(); - let ret = unsafe { - let inserted = &**map.entry(k).or_insert(v); - &*(inserted as *const _) - }; - ret - } - - /// If the key exists in the map, returns a reference to the corresponding - /// value, otherwise inserts a new entry in the map for that key and the - /// value returned by the creation function, and returns a reference to the - /// generated value. - /// - /// Existing values are never overwritten. - /// - /// The key may be any borrowed form of the map's key type, but [`Hash`] and - /// [`Eq`] on the borrowed form *must* match those for the key type. - /// - /// **Note** that the write lock is held for the duration of this function’s - /// execution, even while the value creation function is executing (if - /// needed). This will block any concurrent `get` or `insert` calls. - /// - /// # Examples - /// - /// ``` - /// use lurk::cache_map::CacheMap; - /// - /// let map = CacheMap::new(); - /// assert_eq!(map.insert_with(1, || Box::new("a")), &"a"); - /// assert_eq!(map.insert_with(1, || unreachable!()), &"a"); - /// ``` - pub fn insert_with(&self, k: K, f: impl FnOnce() -> V) -> &V::Target { - let mut map = self.map.write().unwrap(); - let ret = unsafe { - let inserted = &**map.entry(k).or_insert_with(f); - &*(inserted as *const _) - }; - ret - } - - /// If the key exists in the map, returns a reference to the corresponding - /// value, otherwise inserts a new entry in the map for that key and the - /// value returned by the creation function, and returns a reference to the - /// generated value. - /// - /// Existing values are never overwritten. - /// - /// The key may be any borrowed form of the map's key type, but [`Hash`] and - /// [`Eq`] on the borrowed form *must* match those for the key type. - /// - /// **Note** that the write lock is held for the duration of this function’s - /// execution, even while the value creation function is executing (if - /// needed). This will block any concurrent `get` or `insert` calls. - /// - /// # Examples - /// - /// ``` - /// use lurk::cache_map::CacheMap; - /// - /// let map = CacheMap::new(); - /// assert_eq!(map.insert_with_key(1, |_| Box::new("a")), &"a"); - /// assert_eq!(map.insert_with_key(1, |_| unreachable!()), &"a"); - /// ``` - pub fn insert_with_key(&self, k: K, f: impl FnOnce(&K) -> V) -> &V::Target { - let mut map = self.map.write().unwrap(); - let ret = unsafe { - let inserted = &**map.entry(k).or_insert_with_key(f); - &*(inserted as *const _) - }; - ret - } - - /// Returns a reference to the value corresponding to the key. - /// - /// The key may be any borrowed form of the map's key type, but - /// [`Hash`] and [`Eq`] on the borrowed form *must* match those for - /// the key type. - /// - /// # Examples - /// - /// ``` - /// use lurk::cache_map::CacheMap; - /// - /// let map = CacheMap::new(); - /// map.insert(1, Box::new("a")); - /// assert_eq!(map.get(&1), Some(&"a")); - /// assert_eq!(map.get(&2), None); - /// ``` - pub fn get(&self, k: &Q) -> Option<&V::Target> - where - K: Borrow, - Q: Hash + Eq, - { - let map = self.map.read().unwrap(); - let ret = unsafe { map.get(k).map(|x| &*(&**x as *const V::Target)) }; - ret - } - - /// Applies a function to the owner of the value corresponding to the key (if any). - /// - /// The key may be any borrowed form of the map's key type, but - /// [`Hash`] and [`Eq`] on the borrowed form *must* match those for - /// the key type. - /// - /// # Examples - /// - /// ``` - /// use lurk::cache_map::CacheMap; - /// - /// let map = CacheMap::new(); - /// map.insert(1, Box::new("a")); - /// assert_eq!(map.map_get(&1, Clone::clone), Some(Box::new("a"))); - /// assert_eq!(map.map_get(&2, Clone::clone), None); - /// ``` - pub fn map_get(&self, k: &Q, f: F) -> Option - where - K: Borrow, - Q: Hash + Eq, - F: FnOnce(&V) -> T, - { - let map = self.map.read().unwrap(); - let ret = map.get(k).map(f); - ret - } - - /// # Examples - /// - /// ``` - /// use lurk::cache_map::CacheMap; - /// - /// let map = CacheMap::new(); - /// assert_eq!(map.len(), 0); - /// map.insert(1, Box::new("a")); - /// assert_eq!(map.len(), 1); - /// ``` - pub fn len(&self) -> usize { - let map = self.map.read().unwrap(); - map.len() - } - - /// # Examples - /// - /// ``` - /// use lurk::cache_map::CacheMap; - /// - /// let map = CacheMap::new(); - /// assert_eq!(map.is_empty(), true); - /// map.insert(1, Box::new("a")); - /// assert_eq!(map.is_empty(), false); - /// ``` - pub fn is_empty(&self) -> bool { - let map = self.map.read().unwrap(); - map.is_empty() - } - - // TODO add more -} - -impl CacheMap { - pub fn keys_cloned(&self) -> Vec { - self.map.read().unwrap().keys().cloned().collect() - } -} - -impl CacheMap { - /// Returns a copy of the value corresponding to the key. - /// - /// The key may be any borrowed form of the map's key type, but - /// [`Hash`] and [`Eq`] on the borrowed form *must* match those for - /// the key type. - /// - /// # Examples - /// - /// ``` - /// use lurk::cache_map::CacheMap; - /// - /// let map = CacheMap::new(); - /// map.get_copy_or_insert(1, 6); - /// assert_eq!(map.get_copy(&1), Some(6)); - /// assert_eq!(map.get_copy(&2), None); - /// ``` - pub fn get_copy(&self, k: &Q) -> Option - where - K: Borrow, - Q: Hash + Eq, - { - let map = self.map.read().unwrap(); - map.get(k).cloned() - } - - /// If the key exists in the map, returns a reference - /// to the corresponding value, otherwise inserts a - /// new entry in the map for that key and returns a - /// reference to the given value. - /// - /// Existing values are never overwritten. - /// - /// The key may be any borrowed form of the map's key type, but - /// [`Hash`] and [`Eq`] on the borrowed form *must* match those for - /// the key type. - /// - /// # Examples - /// - /// ``` - /// use lurk::cache_map::CacheMap; - /// - /// let map = CacheMap::new(); - /// assert_eq!(map.get_copy_or_insert(1, 6), 6); - /// assert_eq!(map.get_copy_or_insert(1, 12), 6); - /// ``` - pub fn get_copy_or_insert(&self, k: K, v: V) -> V { - let mut map = self.map.write().unwrap(); - // This is safe because `or_insert` does not overwrite existing values - let inserted = map.entry(k).or_insert(v); - *inserted - } - - /// If the key exists in the map, returns a reference to the corresponding - /// value, otherwise inserts a new entry in the map for that key and the - /// value returned by the creation function, and returns a reference to the - /// generated value. - /// - /// Existing values are never overwritten. - /// - /// The key may be any borrowed form of the map's key type, but [`Hash`] and - /// [`Eq`] on the borrowed form *must* match those for the key type. - /// - /// **Note** that the write lock is held for the duration of this function’s - /// execution, even while the value creation function is executing (if - /// needed). This will block any concurrent `get` or `insert` calls. - /// - /// # Examples - /// - /// ``` - /// use lurk::cache_map::CacheMap; - /// - /// let map = CacheMap::new(); - /// assert_eq!(map.get_copy_or_insert_with(1, || 6), 6); - /// assert_eq!(map.get_copy_or_insert_with(1, || unreachable!()), 6); - /// ``` - pub fn get_copy_or_insert_with(&self, k: K, f: impl FnOnce() -> V) -> V { - let mut map = self.map.write().unwrap(); - // This is safe because `or_insert_with` does not overwrite existing values - let inserted = map.entry(k).or_insert_with(f); - *inserted - } - - /// If the key exists in the map, returns a reference to the corresponding - /// value, otherwise inserts a new entry in the map for that key and the - /// value returned by the creation function, and returns a reference to the - /// generated value. - /// - /// Existing values are never overwritten. - /// - /// The key may be any borrowed form of the map's key type, but [`Hash`] and - /// [`Eq`] on the borrowed form *must* match those for the key type. - /// - /// **Note** that the write lock is held for the duration of this function’s - /// execution, even while the value creation function is executing (if - /// needed). This will block any concurrent `get` or `insert` calls. - /// - /// # Examples - /// - /// ``` - /// use lurk::cache_map::CacheMap; - /// - /// let map = CacheMap::new(); - /// assert_eq!(map.get_copy_or_insert_with_key(1, |_| 6), 6); - /// assert_eq!(map.get_copy_or_insert_with_key(1, |_| unreachable!()), 6); - /// ``` - pub fn get_copy_or_insert_with_key(&self, k: K, f: impl FnOnce(&K) -> V) -> V { - let mut map = self.map.write().unwrap(); - // This is safe because `or_insert_with_key` does not overwrite existing values - let inserted = map.entry(k).or_insert_with_key(f); - *inserted - } -} - -impl std::convert::AsMut> for CacheMap { - /// Get mutable access to the underlying [`HashMap`]. - /// - /// This is safe, as it requires a `&mut self`, ensuring nothing is using - /// the 'frozen' contents. - fn as_mut(&mut self) -> &mut HashMap { - self.map.get_mut().unwrap() - } -} diff --git a/src/circuit/circuit_frame.rs b/src/circuit/circuit_frame.rs index a8cc174634..f93d59f503 100644 --- a/src/circuit/circuit_frame.rs +++ b/src/circuit/circuit_frame.rs @@ -523,7 +523,7 @@ impl> CircuitFrame<'_, F, C> { if let Some(store) = self.store { reduce(store) } else { - let mut store: Store = Default::default(); + let store: Store = Default::default(); store.hydrate_scalar_cache(); reduce(&store) } @@ -5479,7 +5479,7 @@ mod tests { }; let raw_lang = Lang::>::new(); let lang = Arc::new(raw_lang.clone()); - let (_, witness, meta) = input.reduce(&mut store, &lang).unwrap(); + let (_, witness, meta) = input.reduce(&store, &lang).unwrap(); let public_params = Groth16Prover::, Fr>::create_groth_params( DEFAULT_REDUCTION_COUNT, @@ -5621,7 +5621,7 @@ mod tests { }; let lang = Arc::new(Lang::>::new()); - let (_, witness, meta) = input.reduce(&mut store, &lang).unwrap(); + let (_, witness, meta) = input.reduce(&store, &lang).unwrap(); store.hydrate_scalar_cache(); let test_with_output = |output: IO, expect_success: bool, store: &Store| { @@ -5705,7 +5705,7 @@ mod tests { }; let lang = Arc::new(Lang::>::new()); - let (_, witness, meta) = input.reduce(&mut store, &lang).unwrap(); + let (_, witness, meta) = input.reduce(&store, &lang).unwrap(); store.hydrate_scalar_cache(); let test_with_output = |output: IO, expect_success: bool, store: &Store| { @@ -5791,7 +5791,7 @@ mod tests { }; let lang = Arc::new(Lang::>::new()); - let (_, witness, meta) = input.reduce(&mut store, &lang).unwrap(); + let (_, witness, meta) = input.reduce(&store, &lang).unwrap(); store.hydrate_scalar_cache(); @@ -5879,7 +5879,7 @@ mod tests { }; let lang = Arc::new(Lang::>::new()); - let (_, witness, meta) = input.reduce(&mut store, &lang).unwrap(); + let (_, witness, meta) = input.reduce(&store, &lang).unwrap(); store.hydrate_scalar_cache(); diff --git a/src/circuit/gadgets/circom/mod.rs b/src/circuit/gadgets/circom/mod.rs index 1ae3e68527..c3912f898d 100644 --- a/src/circuit/gadgets/circom/mod.rs +++ b/src/circuit/gadgets/circom/mod.rs @@ -22,5 +22,5 @@ pub trait CircomGadget: Send + Sync + Clone { fn into_circom_input(self, input: &[AllocatedPtr]) -> Vec<(String, Vec)>; - fn simple_evaluate(&self, s: &mut Store, args: &[Ptr]) -> Ptr; + fn simple_evaluate(&self, s: &Store, args: &[Ptr]) -> Ptr; } diff --git a/src/cli/commitment.rs b/src/cli/commitment.rs index 253e8bca99..973b79b768 100644 --- a/src/cli/commitment.rs +++ b/src/cli/commitment.rs @@ -27,7 +27,7 @@ impl HasFieldModulus for Commitment { } impl Commitment { - pub(crate) fn new(secret: Option, payload: Ptr, store: &mut Store) -> Result { + pub(crate) fn new(secret: Option, payload: Ptr, store: &Store) -> Result { let comm_ptr = match secret { Some(secret) => store.hide(secret, payload), None => store.commit(payload), diff --git a/src/cli/repl.rs b/src/cli/repl.rs index f1ac9cbeb7..74febe9d6d 100644 --- a/src/cli/repl.rs +++ b/src/cli/repl.rs @@ -223,7 +223,7 @@ impl Repl { (cont.parts(), cont_out.parts()), ); - let claim_comm = Commitment::new(None, claim, &mut self.store)?; + let claim_comm = Commitment::new(None, claim, &self.store)?; let claim_hash = &claim_comm.hash.hex_digits(); let proof_key = &Self::proof_key(&self.backend, &self.rc, claim_hash); let proof_path = proof_path(proof_key); @@ -282,7 +282,7 @@ impl Repl { } fn hide(&mut self, secret: F, payload: Ptr) -> Result<()> { - let commitment = Commitment::new(Some(secret), payload, &mut self.store)?; + let commitment = Commitment::new(Some(secret), payload, &self.store)?; let hash_str = &commitment.hash.hex_digits(); commitment.persist()?; println!( @@ -324,8 +324,7 @@ impl Repl { } fn eval_expr(&mut self, expr_ptr: Ptr) -> Result<(IO, usize, Vec>)> { - let ret = - Evaluator::new(expr_ptr, self.env, &mut self.store, self.limit, &self.lang).eval()?; + let ret = Evaluator::new(expr_ptr, self.env, &self.store, self.limit, &self.lang).eval()?; match ret.0.cont.tag { ContTag::Terminal => Ok(ret), t => { @@ -344,8 +343,7 @@ impl Repl { &mut self, expr_ptr: Ptr, ) -> Result<(IO, usize, Vec>)> { - let ret = - Evaluator::new(expr_ptr, self.env, &mut self.store, self.limit, &self.lang).eval()?; + let ret = Evaluator::new(expr_ptr, self.env, &self.store, self.limit, &self.lang).eval()?; if matches!(ret.0.cont.tag, ContTag::Terminal | ContTag::Error) { Ok(ret) } else { @@ -357,8 +355,8 @@ impl Repl { } fn eval_expr_and_memoize(&mut self, expr_ptr: Ptr) -> Result<(IO, usize)> { - let frames = Evaluator::new(expr_ptr, self.env, &mut self.store, self.limit, &self.lang) - .get_frames()?; + let frames = + Evaluator::new(expr_ptr, self.env, &self.store, self.limit, &self.lang).get_frames()?; let n_frames = frames.len(); let last_frame = &frames[n_frames - 1]; diff --git a/src/cont.rs b/src/cont.rs index 4954497d52..651becb743 100644 --- a/src/cont.rs +++ b/src/cont.rs @@ -69,7 +69,7 @@ pub enum Continuation { } impl Continuation { - pub(crate) fn intern_aux(&self, store: &mut crate::store::Store) -> ContPtr { + pub(crate) fn intern_aux(&self, store: &crate::store::Store) -> ContPtr { match self { Self::Outermost | Self::Dummy | Self::Error | Self::Terminal => { let cont_ptr = self.get_simple_cont(); @@ -80,67 +80,79 @@ impl Continuation { let (p, inserted) = self.insert_in_store(store); let ptr = ContPtr::index(self.cont_tag(), p); if inserted { - store.dehydrated_cont.push(ptr) + store.dehydrated_cont.load().push(Box::new(ptr)) } ptr } } } - pub fn insert_in_store(&self, store: &mut crate::store::Store) -> (usize, bool) { + pub fn insert_in_store(&self, store: &crate::store::Store) -> (usize, bool) { match self { Self::Outermost | Self::Dummy | Self::Error | Self::Terminal => (0, false), Self::Call0 { saved_env, continuation, - } => store.call0_store.insert_full((*saved_env, *continuation)), + } => store + .call0_store + .insert_probe(Box::new((*saved_env, *continuation))), Self::Call { unevaled_arg, saved_env, continuation, - } => store - .call_store - .insert_full((*unevaled_arg, *saved_env, *continuation)), + } => { + store + .call_store + .insert_probe(Box::new((*unevaled_arg, *saved_env, *continuation))) + } Self::Call2 { function, saved_env, continuation, } => store .call2_store - .insert_full((*function, *saved_env, *continuation)), + .insert_probe(Box::new((*function, *saved_env, *continuation))), Self::Tail { saved_env, continuation, - } => store.tail_store.insert_full((*saved_env, *continuation)), + } => store + .tail_store + .insert_probe(Box::new((*saved_env, *continuation))), Self::Lookup { saved_env, continuation, - } => store.lookup_store.insert_full((*saved_env, *continuation)), + } => store + .lookup_store + .insert_probe(Box::new((*saved_env, *continuation))), Self::Unop { operator, continuation, - } => store.unop_store.insert_full((*operator, *continuation)), + } => store + .unop_store + .insert_probe(Box::new((*operator, *continuation))), Self::Binop { operator, saved_env, unevaled_args, continuation, - } => store.binop_store.insert_full(( + } => store.binop_store.insert_probe(Box::new(( *operator, *saved_env, *unevaled_args, *continuation, - )), + ))), Self::Binop2 { operator, evaled_arg, continuation, } => store .binop2_store - .insert_full((*operator, *evaled_arg, *continuation)), + .insert_probe(Box::new((*operator, *evaled_arg, *continuation))), Self::If { unevaled_args, continuation, - } => store.if_store.insert_full((*unevaled_args, *continuation)), + } => store + .if_store + .insert_probe(Box::new((*unevaled_args, *continuation))), Self::Let { var, body, @@ -148,16 +160,18 @@ impl Continuation { continuation, } => store .let_store - .insert_full((*var, *body, *saved_env, *continuation)), + .insert_probe(Box::new((*var, *body, *saved_env, *continuation))), Self::LetRec { var, body, saved_env, continuation, - } => store - .letrec_store - .insert_full((*var, *body, *saved_env, *continuation)), - Self::Emit { continuation } => store.emit_store.insert_full(*continuation), + } => { + store + .letrec_store + .insert_probe(Box::new((*var, *body, *saved_env, *continuation))) + } + Self::Emit { continuation } => store.emit_store.insert_probe(Box::new(*continuation)), } } diff --git a/src/coprocessor/circom.rs b/src/coprocessor/circom.rs index c9a0955e7c..7b3662786e 100644 --- a/src/coprocessor/circom.rs +++ b/src/coprocessor/circom.rs @@ -141,7 +141,7 @@ Then run `lurk coprocessor --name {name} <{}_FOLDER>` to instantiate a new gadge 0 } - fn simple_evaluate(&self, s: &mut Store, args: &[Ptr]) -> Ptr { + fn simple_evaluate(&self, s: &Store, args: &[Ptr]) -> Ptr { self.gadget.simple_evaluate(s, args) } diff --git a/src/coprocessor/mod.rs b/src/coprocessor/mod.rs index 932910647a..4f25d2c04d 100644 --- a/src/coprocessor/mod.rs +++ b/src/coprocessor/mod.rs @@ -33,7 +33,7 @@ pub mod trie; pub trait Coprocessor: Clone + Debug + Sync + Send + CoCircuit { fn eval_arity(&self) -> usize; - fn evaluate(&self, s: &mut Store, args: Ptr, env: Ptr, cont: ContPtr) -> IO { + fn evaluate(&self, s: &Store, args: Ptr, env: Ptr, cont: ContPtr) -> IO { let Some(argv) = s.fetch_list(&args) else { return IO { expr: args, @@ -60,7 +60,7 @@ pub trait Coprocessor: Clone + Debug + Sync + Send + CoCircuit } /// As with all evaluation, the value returned from `simple_evaluate` must be fully evaluated. - fn simple_evaluate(&self, s: &mut Store, args: &[Ptr]) -> Ptr; + fn simple_evaluate(&self, s: &Store, args: &[Ptr]) -> Ptr; /// Returns true if this Coprocessor actually implements a circuit. fn has_circuit(&self) -> bool { @@ -220,7 +220,7 @@ pub(crate) mod test { } /// It squares the first arg and adds it to the second. - fn simple_evaluate(&self, s: &mut Store, args: &[Ptr]) -> Ptr { + fn simple_evaluate(&self, s: &Store, args: &[Ptr]) -> Ptr { let a = args[0]; let b = args[1]; diff --git a/src/coprocessor/trie/mod.rs b/src/coprocessor/trie/mod.rs index 081a720c0c..92f17a0074 100644 --- a/src/coprocessor/trie/mod.rs +++ b/src/coprocessor/trie/mod.rs @@ -62,7 +62,7 @@ impl Coprocessor for NewCoprocessor { 0 } - fn simple_evaluate(&self, s: &mut Store, _args: &[Ptr]) -> Ptr { + fn simple_evaluate(&self, s: &Store, _args: &[Ptr]) -> Ptr { let trie: Trie<'_, F, 8, 85> = Trie::new(s); let root = trie.root; @@ -84,7 +84,7 @@ impl Coprocessor for LookupCoprocessor { 2 } - fn simple_evaluate(&self, s: &mut Store, args: &[Ptr]) -> Ptr { + fn simple_evaluate(&self, s: &Store, args: &[Ptr]) -> Ptr { let root_ptr = args[0]; let key_ptr = args[1]; let root_scalar = *s.hash_expr(&root_ptr).unwrap().value(); @@ -109,7 +109,7 @@ impl Coprocessor for InsertCoprocessor { 3 } - fn simple_evaluate(&self, s: &mut Store, args: &[Ptr]) -> Ptr { + fn simple_evaluate(&self, s: &Store, args: &[Ptr]) -> Ptr { let root_ptr = args[0]; let key_ptr = args[1]; let val_ptr = args[2]; @@ -129,7 +129,7 @@ impl CoCircuit for InsertCoprocessor {} /// Add the `Trie`-associated functions to a `Lang` with standard bindings. // TODO: define standard patterns for such modularity. pub fn install( - s: &mut Store, + s: &Store, state: Rc>, lang: &mut Lang>, ) { @@ -160,7 +160,7 @@ pub struct Trie<'a, F: LurkField, const ARITY: usize, const HEIGHT: usize> { root: F, empty_roots: [F; HEIGHT], hash_cache: &'a PoseidonCache, - children: &'a mut ChildMap, + children: &'a ChildMap, } #[derive(Debug)] @@ -326,22 +326,22 @@ impl<'a, F: LurkField, const ARITY: usize, const HEIGHT: usize> Trie<'a, F, ARIT /// Creates a new `Trie`, saving preimage data in `store`. /// HEIGHT must be exactly that required to minimally store all elements of `F`. - pub fn new(store: &'a mut Store) -> Self { + pub fn new(store: &'a Store) -> Self { Self::new_aux(store, None) } /// Creates a new `Trie`, saving preimage data in `store`. /// Height must be at least that required to store `size` elements. - pub fn new_with_capacity(store: &'a mut Store, size: usize) -> Self { + pub fn new_with_capacity(store: &'a Store, size: usize) -> Self { Self::new_aux(store, Some(size)) } - fn new_aux(store: &'a mut Store, size: Option) -> Self { + fn new_aux(store: &'a Store, size: Option) -> Self { // ARITY must be a power of two. assert_eq!(1, ARITY.count_ones()); let poseidon_cache = &store.poseidon_cache; - let inverse_poseidon_cache = &mut store.inverse_poseidon_cache; + let inverse_poseidon_cache = &store.inverse_poseidon_cache; // This will panic if ARITY is unsupporteed. let _ = HashArity::from(ARITY); @@ -383,7 +383,7 @@ impl<'a, F: LurkField, const ARITY: usize, const HEIGHT: usize> Trie<'a, F, ARIT } /// Create a new `Trie` with specified root. - fn new_with_root(store: &'a mut Store, root: F) -> Self { + fn new_with_root(store: &'a Store, root: F) -> Self { let mut new = Self::new(store); new.root = root; diff --git a/src/eval/lang.rs b/src/eval/lang.rs index 651852bb84..9b21855b80 100644 --- a/src/eval/lang.rs +++ b/src/eval/lang.rs @@ -35,7 +35,7 @@ impl Coprocessor for DummyCoprocessor { /// And does nothing but return nil. It should probably never be used and can perhaps be eliminated, /// but for now it exists as an exemplar demonstrating the intended shape of enums like the default, `Coproc`. - fn simple_evaluate(&self, s: &mut Store, args: &[Ptr]) -> Ptr { + fn simple_evaluate(&self, s: &Store, args: &[Ptr]) -> Ptr { assert!(args.is_empty()); lurk_sym_ptr!(s, nil) } @@ -93,7 +93,7 @@ impl> Lang { } } - pub fn new_with_bindings>>(s: &mut Store, bindings: Vec) -> Self { + pub fn new_with_bindings>>(s: &Store, bindings: Vec) -> Self { let mut new = Self::new(); for b in bindings { new.add_binding(b.into(), s); @@ -119,18 +119,17 @@ impl> Lang { &mut self, name: S, cproc: T, - store: &mut Store, + store: &Store, ) { let name = name.into(); let ptr = store.intern_symbol(&name); let z_ptr = store.hash_expr(&ptr).unwrap(); - self.coprocessors - .insert(name.clone(), (cproc.into(), z_ptr)); + self.coprocessors.insert(name, (cproc.into(), z_ptr)); self.index.insert(z_ptr, self.index.len()); } - pub fn add_binding>>(&mut self, binding: B, store: &mut Store) { + pub fn add_binding>>(&mut self, binding: B, store: &Store) { let Binding { name, coproc, _p } = binding.into(); self.add_coprocessor(name, coproc, store); } diff --git a/src/eval/mod.rs b/src/eval/mod.rs index 44fd0122ed..d27fa748c5 100644 --- a/src/eval/mod.rs +++ b/src/eval/mod.rs @@ -151,7 +151,7 @@ impl Status { } } - pub fn to_cont(&self, s: &mut Store) -> Option> { + pub fn to_cont(&self, s: &Store) -> Option> { match self { Self::Terminal => Some(s.intern_cont_terminal()), Self::Error => Some(s.intern_cont_error()), @@ -201,7 +201,7 @@ impl> Frame, W, F, C> { pub trait Evaluable> { fn reduce( &self, - store: &mut Store, + store: &Store, lang: &Lang, ) -> Result<(Self, W, Meta), ReductionError> where @@ -218,7 +218,7 @@ pub trait Evaluable> { impl> Evaluable, C> for IO { fn reduce( &self, - store: &mut Store, + store: &Store, lang: &Lang, ) -> Result<(Self, Witness, Meta), ReductionError> { let (expr, env, cont, witness, meta) = @@ -303,11 +303,7 @@ impl IO { impl, C> + Copy, C: Coprocessor> Frame, F, C> { - pub(crate) fn next( - &self, - store: &mut Store, - lang: &Lang, - ) -> Result { + pub(crate) fn next(&self, store: &Store, lang: &Lang) -> Result { let input = self.output; let (output, witness, meta) = input.reduce(store, lang)?; @@ -330,7 +326,7 @@ impl, C> + Copy, C: Coprocessor + Cl { fn from_initial_input( input: T, - store: &mut Store, + store: &Store, lang: &Lang, ) -> Result { input.log(store, 0); @@ -350,14 +346,14 @@ impl, C> + Copy, C: Coprocessor + Cl pub struct FrameIt<'a, W: Copy, F: LurkField, C: Coprocessor> { first: bool, frame: Frame, W, F, C>, - store: &'a mut Store, + store: &'a Store, lang: &'a Lang, } impl<'a, F: LurkField, C: Coprocessor> FrameIt<'a, Witness, F, C> { fn new( initial_input: IO, - store: &'a mut Store, + store: &'a Store, lang: &'a Lang, ) -> Result { let frame = Frame::from_initial_input(initial_input, store, lang)?; @@ -442,7 +438,7 @@ where pub fn new( expr: Ptr, env: Ptr, - store: &'a mut Store, + store: &'a Store, limit: usize, lang: &'a Lang, ) -> Self { @@ -569,7 +565,7 @@ pub fn eval_to_ptr>( pub struct Evaluator<'a, F: LurkField, C: Coprocessor> { expr: Ptr, env: Ptr, - store: &'a mut Store, + store: &'a Store, limit: usize, lang: &'a Lang, } diff --git a/src/eval/reduction.rs b/src/eval/reduction.rs index d740c6ea00..d8d4a5e4b9 100644 --- a/src/eval/reduction.rs +++ b/src/eval/reduction.rs @@ -18,7 +18,7 @@ pub(crate) fn reduce>( expr: Ptr, env: Ptr, cont: ContPtr, - store: &mut Store, + store: &Store, lang: &Lang, ) -> Result<(Ptr, Ptr, ContPtr, Witness, Meta), ReductionError> { let c = *store.expect_constants(); @@ -37,7 +37,7 @@ enum Control { } impl Control { - fn into_results(self, store: &mut Store) -> (Ptr, Ptr, ContPtr) { + fn into_results(self, store: &Store) -> (Ptr, Ptr, ContPtr) { match self { Self::Return(expr, env, cont) | Self::MakeThunk(expr, env, cont) @@ -61,7 +61,7 @@ fn reduce_with_witness_inner>( expr: Ptr, env: Ptr, cont: ContPtr, - store: &mut Store, + store: &Store, cons_witness: &mut ConsWitness, cont_witness: &mut ContWitness, c: &NamedConstants, @@ -656,7 +656,7 @@ fn reduce_with_witness>( expr: Ptr, env: Ptr, cont: ContPtr, - store: &mut Store, + store: &Store, c: &NamedConstants, lang: &Lang, ) -> Result<(Control, Witness, Meta), ReductionError> { @@ -691,7 +691,7 @@ fn reduce_with_witness>( fn apply_continuation( control: Control, - store: &mut Store, + store: &Store, witness: &mut Witness, c: &NamedConstants, ) -> Result, ReductionError> { @@ -1027,7 +1027,7 @@ fn apply_continuation( } => { let arg2 = result; - let num_num = |store: &mut Store, + let num_num = |store: &Store, operator, a: Num, b: Num| @@ -1251,7 +1251,7 @@ fn apply_continuation( // Returns (Expression::Thunk, Expression::Env, Continuation) fn make_thunk( control: Control, - store: &mut Store, + store: &Store, witness: &mut Witness, ) -> Result, ReductionError> { if !control.is_make_thunk() { @@ -1299,7 +1299,7 @@ fn make_thunk( fn make_tail_continuation( env: Ptr, continuation: ContPtr, - store: &mut Store, + store: &Store, cont_witness: &mut ContWitness, ) -> ContPtr { // Result must be either a Tail or Outermost continuation. @@ -1327,7 +1327,7 @@ pub(crate) fn extend( env: Ptr, var: Ptr, val: Ptr, - store: &mut Store, + store: &Store, ) -> Ptr { let cons = store.cons(var, val); store.cons(cons, env) @@ -1337,7 +1337,7 @@ fn extend_rec( env: Ptr, var: Ptr, val: Ptr, - store: &mut Store, + store: &Store, cons_witness: &mut ConsWitness, ) -> Result, ReductionError> { let (binding_or_env, rest) = cons_witness.car_cdr_named(ConsName::Env, store, &env)?; @@ -1367,7 +1367,7 @@ fn extend_rec( fn extend_closure( fun: &Ptr, rec_env: &Ptr, - store: &mut Store, + store: &Store, cons_witness: &mut ConsWitness, ) -> Result, ReductionError> { match fun.tag { @@ -1393,7 +1393,7 @@ fn extend_closure( } impl Store { - pub fn as_lurk_boolean(&mut self, x: bool) -> Ptr { + pub fn as_lurk_boolean(&self, x: bool) -> Ptr { if x { lurk_sym_ptr!(self, t) } else { diff --git a/src/eval/tests/mod.rs b/src/eval/tests/mod.rs index 5bc05451e4..e7fbed55ef 100644 --- a/src/eval/tests/mod.rs +++ b/src/eval/tests/mod.rs @@ -146,7 +146,7 @@ fn test_lookup() { assert!(lookup(&env, &var, &store).unwrap().is_nil()); - let new_env = extend(env, var, val, &mut store); + let new_env = extend(env, var, val, &store); assert_eq!(val, lookup(&new_env, &var, &store).unwrap()); } @@ -161,7 +161,7 @@ fn test_reduce_simple() { num, empty_sym_env(&store), store.intern_cont_outermost(), - &mut store, + &store, &lang, ) .unwrap(); @@ -173,7 +173,7 @@ fn test_reduce_simple() { lurk_sym_ptr!(store, nil), empty_sym_env(&store), store.intern_cont_outermost(), - &mut store, + &store, &lang, ) .unwrap(); @@ -199,7 +199,7 @@ fn evaluate_lookup() { let var = store.sym("apple"); let val2 = store.num(888); let var2 = store.sym("banana"); - let env = extend(empty_sym_env(&store), var, val, &mut store); + let env = extend(empty_sym_env(&store), var, val, &store); let lang = Lang::>::new(); { @@ -211,7 +211,7 @@ fn evaluate_lookup() { }, iterations, _emitted, - ) = Evaluator::new(var, env, &mut store, limit, &lang) + ) = Evaluator::new(var, env, &store, limit, &lang) .eval() .unwrap(); @@ -219,7 +219,7 @@ fn evaluate_lookup() { assert_eq!(&result_expr, &val); } { - let env2 = extend(env, var2, val2, &mut store); + let env2 = extend(env, var2, val2, &store); let ( IO { expr: result_expr, @@ -228,7 +228,7 @@ fn evaluate_lookup() { }, iterations, _emitted, - ) = Evaluator::new(var, env2, &mut store, limit, &lang) + ) = Evaluator::new(var, env2, &store, limit, &lang) .eval() .unwrap(); @@ -1133,7 +1133,7 @@ fn evaluate_make_tree_minimal_regression() { }, iterations, _emitted, - ) = Evaluator::new(expr, empty_sym_env(&s), &mut s, limit, &lang) + ) = Evaluator::new(expr, empty_sym_env(&s), &s, limit, &lang) .eval() .unwrap(); diff --git a/src/hash.rs b/src/hash.rs index 00463144e5..95f0b49af6 100644 --- a/src/hash.rs +++ b/src/hash.rs @@ -1,9 +1,8 @@ -use std::collections::HashMap; use std::hash::Hash; use std::sync::Arc; -use crate::cache_map::CacheMap; use crate::field::{FWrap, LurkField}; +use elsa::{sync::FrozenMap, sync_index_map::FrozenIndexMap}; use generic_array::typenum::{U3, U4, U6, U8}; use neptune::{poseidon::PoseidonConstants, Poseidon}; @@ -86,10 +85,10 @@ impl HashConstants { #[derive(Clone, Default, Debug)] pub struct PoseidonCache { - a3: Arc, F>>, - a4: Arc, F>>, - a6: Arc, F>>, - a8: Arc, F>>, + a3: Arc, F>>, + a4: Arc, F>>, + a6: Arc, F>>, + a8: Arc, F>>, pub constants: HashConstants, } @@ -114,12 +113,12 @@ impl PoseidonCache { } } -#[derive(Clone, Default, Debug)] +#[derive(Default, Debug)] pub struct InversePoseidonCache { - a3: HashMap, [F; 3]>, - a4: HashMap, [F; 4]>, - a6: HashMap, [F; 6]>, - a8: HashMap, [F; 8]>, + a3: FrozenIndexMap, Box<[F; 3]>>, + a4: FrozenIndexMap, Box<[F; 4]>>, + a6: FrozenIndexMap, Box<[F; 6]>>, + a8: FrozenIndexMap, Box<[F; 8]>>, pub constants: HashConstants, } @@ -148,15 +147,15 @@ impl InversePoseidonCache { _ => unreachable!(), } } - pub fn insert(&mut self, key: FWrap, preimage: [F; ARITY]) { + pub fn insert(&self, key: FWrap, preimage: [F; ARITY]) { macro_rules! insert { ($name:ident, $n:expr) => {{ assert_eq!(ARITY, $n); // SAFETY: we are just teaching the compiler that the slice has size, ARITY, which is guaranteed by // the assertion above. - self.$name.insert(key, unsafe { + self.$name.insert(key, Box::new(unsafe { *std::mem::transmute::<&[F; ARITY], &[F; $n]>(&preimage) - }); + })); }}; } diff --git a/src/hash_witness.rs b/src/hash_witness.rs index 65e705ecf3..a7557f3302 100644 --- a/src/hash_witness.rs +++ b/src/hash_witness.rs @@ -296,7 +296,7 @@ impl ConsStub { } } - pub fn cons(&mut self, store: &mut Store, car: Ptr, cdr: Ptr) -> Ptr { + pub fn cons(&mut self, store: &Store, car: Ptr, cdr: Ptr) -> Ptr { match self { Self::Dummy => { let cons = Cons::cons(store, car, cdr); @@ -309,7 +309,7 @@ impl ConsStub { Self::Value(_) => Cons::cons(store, car, cdr), } } - pub fn strcons(&mut self, store: &mut Store, car: Ptr, cdr: Ptr) -> Ptr { + pub fn strcons(&mut self, store: &Store, car: Ptr, cdr: Ptr) -> Ptr { match self { Self::Dummy => { let cons = Cons::strcons(store, car, cdr); @@ -530,7 +530,7 @@ impl ConsWitness { pub fn cons_named( &mut self, name: ConsName, - store: &mut Store, + store: &Store, car: Ptr, cdr: Ptr, ) -> Ptr { @@ -540,7 +540,7 @@ impl ConsWitness { pub fn strcons_named( &mut self, name: ConsName, - store: &mut Store, + store: &Store, car: Ptr, cdr: Ptr, ) -> Ptr { @@ -562,7 +562,7 @@ impl ConsWitness { env: Ptr, var: Ptr, val: Ptr, - store: &mut Store, + store: &Store, ) -> Ptr { let binding = self.cons_named(ConsName::Binding, store, var, val); @@ -571,11 +571,11 @@ impl ConsWitness { } impl Cons { - fn cons(store: &mut Store, car: Ptr, cdr: Ptr) -> Ptr { + fn cons(store: &Store, car: Ptr, cdr: Ptr) -> Ptr { store.cons(car, cdr) } - fn strcons(store: &mut Store, car: Ptr, cdr: Ptr) -> Ptr { + fn strcons(store: &Store, car: Ptr, cdr: Ptr) -> Ptr { store.strcons(car, cdr) } @@ -603,7 +603,7 @@ impl ContWitness { pub fn intern_named_cont( &mut self, name: ContName, - store: &mut Store, + store: &Store, continuation: Continuation, ) -> ContPtr { self.get_assigned_slot(name) @@ -628,11 +628,7 @@ impl ContStub { Self::Value(h) => Some(h.fetch_cont(cont)), } } - pub fn intern_cont( - &mut self, - store: &mut Store, - continuation: Continuation, - ) -> ContPtr { + pub fn intern_cont(&mut self, store: &Store, continuation: Continuation) -> ContPtr { match self { Self::Dummy => { let cont_ptr = continuation.intern_aux(store); diff --git a/src/lem/circuit.rs b/src/lem/circuit.rs index 15e180554d..42470a1b6f 100644 --- a/src/lem/circuit.rs +++ b/src/lem/circuit.rs @@ -307,7 +307,7 @@ impl Block { g.new_const(cs, tag.to_field()); } Op::Lit(_, lit) => { - let lit_ptr = lit.to_ptr_cached(store); + let lit_ptr = lit.to_ptr(store); let lit_z_ptr = store.hash_ptr(&lit_ptr).unwrap(); g.new_const(cs, lit_z_ptr.tag_field()); g.new_const(cs, *lit_z_ptr.value()); @@ -679,7 +679,7 @@ impl Func { bound_allocations.insert_ptr(tgt.clone(), allocated_ptr); } Op::Lit(tgt, lit) => { - let lit_ptr = lit.to_ptr_cached(g.store); + let lit_ptr = lit.to_ptr(g.store); let lit_tag = lit_ptr.tag().to_field(); let allocated_tag = g.global_allocator.get_allocated_const_cloned(lit_tag)?; @@ -1098,11 +1098,8 @@ impl Func { let mut cases_vec = Vec::with_capacity(cases.len()); for (sym, block) in cases { - let sym_ptr = g - .store - .interned_symbol(sym) - .expect("symbol must have been interned"); - let sym_hash = *g.store.hash_ptr(sym_ptr)?.value(); + let sym_ptr = g.store.intern_symbol(sym); + let sym_hash = *g.store.hash_ptr(&sym_ptr)?.value(); cases_vec.push((sym_hash, block)); } @@ -1200,7 +1197,7 @@ impl Func { } } Op::Lit(_, lit) => { - let lit_ptr = lit.to_ptr_cached(store); + let lit_ptr = lit.to_ptr(store); let lit_z_ptr = store.hash_ptr(&lit_ptr).unwrap(); globals.insert(FWrap(lit_z_ptr.tag_field())); globals.insert(FWrap(*lit_z_ptr.value())); diff --git a/src/lem/eval.rs b/src/lem/eval.rs index b482effcd5..31257b0d0b 100644 --- a/src/lem/eval.rs +++ b/src/lem/eval.rs @@ -32,7 +32,7 @@ pub fn evaluate_with_env_and_cont( expr: Ptr, env: Ptr, cont: Ptr, - store: &mut Store, + store: &Store, limit: usize, ) -> Result<(Vec>, usize)> { let stop_cond = |output: &[Ptr]| { @@ -60,7 +60,7 @@ pub fn evaluate_with_env_and_cont( pub fn evaluate( expr: Ptr, - store: &mut Store, + store: &Store, limit: usize, ) -> Result<(Vec>, usize)> { evaluate_with_env_and_cont( @@ -74,7 +74,7 @@ pub fn evaluate( pub fn evaluate_simple( expr: Ptr, - store: &mut Store, + store: &Store, limit: usize, ) -> Result<(Vec>, usize, Vec>)> { let stop_cond = |output: &[Ptr]| { @@ -1179,7 +1179,7 @@ mod tests { fn test_eval_and_constrain_aux( eval_step: &Func, - store: &mut Store, + store: &Store, pairs: Vec<(Ptr, Ptr)>, ) { assert_eq!(eval_step.slot, NUM_SLOTS); @@ -1236,9 +1236,9 @@ mod tests { // eval_step.assert_all_paths_taken(&all_paths); } - fn expr_in_expr_out_pairs(s: &mut Store) -> Vec<(Ptr, Ptr)> { + fn expr_in_expr_out_pairs(s: &Store) -> Vec<(Ptr, Ptr)> { let state = State::init_lurk_state().rccell(); - let mut read = |code: &str| s.read(state.clone(), code).unwrap(); + let read = |code: &str| s.read(state.clone(), code).unwrap(); let div = read("(/ 70u64 8u64)"); let div_res = read("8u64"); let rem = read("(% 70u64 8u64)"); @@ -1314,9 +1314,9 @@ mod tests { #[test] fn test_pairs() { let step_fn = eval_step(); - let store = &mut step_fn.init_store(); - let pairs = expr_in_expr_out_pairs(store); + let store = step_fn.init_store(); + let pairs = expr_in_expr_out_pairs(&store); store.hydrate_z_cache(); - test_eval_and_constrain_aux(step_fn, store, pairs); + test_eval_and_constrain_aux(step_fn, &store, pairs); } } diff --git a/src/lem/interpreter.rs b/src/lem/interpreter.rs index 5814e3d495..813a09a83e 100644 --- a/src/lem/interpreter.rs +++ b/src/lem/interpreter.rs @@ -138,7 +138,7 @@ impl Block { fn run( &self, input: &[Ptr], - store: &mut Store, + store: &Store, mut bindings: VarMap>, mut preimages: Preimages, mut path: Path, @@ -471,7 +471,7 @@ impl Func { pub fn call( &self, args: &[Ptr], - store: &mut Store, + store: &Store, preimages: Preimages, emitted: &mut Vec>, ) -> Result<(Frame, Path)> { @@ -528,7 +528,7 @@ impl Func { >( &self, args: &[Ptr], - store: &mut Store, + store: &Store, stop_cond: StopCond, limit: usize, // TODO: make this argument optional @@ -574,7 +574,7 @@ impl Func { pub fn call_until_simple]) -> bool>( &self, args: Vec>, - store: &mut Store, + store: &Store, stop_cond: StopCond, limit: usize, ) -> Result<(Vec>, usize, Vec>)> { diff --git a/src/lem/mod.rs b/src/lem/mod.rs index 6b0eef2950..4b7ae580de 100644 --- a/src/lem/mod.rs +++ b/src/lem/mod.rs @@ -185,7 +185,7 @@ pub enum Lit { } impl Lit { - pub fn to_ptr(&self, store: &mut Store) -> Ptr { + pub fn to_ptr(&self, store: &Store) -> Ptr { match self { Self::Symbol(s) => store.intern_symbol(s), Self::String(s) => store.intern_string(s), @@ -193,18 +193,6 @@ impl Lit { } } - pub fn to_ptr_cached(&self, store: &Store) -> Ptr { - match self { - Self::Symbol(s) => *store - .interned_symbol(s) - .expect("Symbol should have been cached"), - Self::String(s) => *store - .interned_string(s) - .expect("String should have been cached"), - Self::Num(num) => Ptr::num(F::from_u128(*num)), - } - } - pub fn from_ptr(ptr: &Ptr, store: &Store) -> Option { use ExprTag::{Num, Str, Sym}; use Tag::Expr; @@ -582,8 +570,8 @@ impl Func { } pub fn init_store(&self) -> Store { - let mut store = Store::default(); - self.body.intern_lits(&mut store); + let store = Store::default(); + self.body.intern_lits(&store); store } } @@ -774,7 +762,7 @@ impl Block { Ok(Block { ops, ctrl }) } - fn intern_lits(&self, store: &mut Store) { + fn intern_lits(&self, store: &Store) { for op in &self.ops { match op { Op::Call(_, func, _) => func.body.intern_lits(store), diff --git a/src/lem/store.rs b/src/lem/store.rs index cbc2ccc449..9a93ab47d4 100644 --- a/src/lem/store.rs +++ b/src/lem/store.rs @@ -1,11 +1,12 @@ use anyhow::{bail, Result}; -use indexmap::IndexSet; +use arc_swap::ArcSwap; +use elsa::sync::{FrozenMap, FrozenVec}; +use elsa::sync_index_set::FrozenIndexSet; use nom::{sequence::preceded, Parser}; -use rayon::prelude::*; -use std::{cell::RefCell, collections::HashMap, rc::Rc}; +use rayon::prelude::{IntoParallelRefIterator, ParallelIterator}; +use std::{cell::RefCell, rc::Rc, sync::Arc}; use crate::{ - cache_map::CacheMap, field::{FWrap, LurkField}, hash::PoseidonCache, lem::Tag, @@ -39,32 +40,32 @@ use super::pointers::{Ptr, ZPtr}; /// the resulting commitment hash. #[derive(Default, Debug)] pub struct Store { - tuple2: IndexSet<(Ptr, Ptr)>, - tuple3: IndexSet<(Ptr, Ptr, Ptr)>, - tuple4: IndexSet<(Ptr, Ptr, Ptr, Ptr)>, + tuple2: FrozenIndexSet, Ptr)>>, + tuple3: FrozenIndexSet, Ptr, Ptr)>>, + tuple4: FrozenIndexSet, Ptr, Ptr, Ptr)>>, - string_ptr_cache: HashMap>, - symbol_ptr_cache: HashMap>, + string_ptr_cache: FrozenMap>>, + symbol_ptr_cache: FrozenMap>>, - ptr_string_cache: CacheMap, String>, - ptr_symbol_cache: CacheMap, Box>, + ptr_string_cache: FrozenMap, String>, + ptr_symbol_cache: FrozenMap, Box>, pub poseidon_cache: PoseidonCache, - dehydrated: Vec>, - z_cache: CacheMap, Box>>, + dehydrated: ArcSwap>>>, + z_cache: FrozenMap, Box>>, - comms: HashMap, (F, Ptr)>, // hash -> (secret, src) + comms: FrozenMap, Box<(F, Ptr)>>, // hash -> (secret, src) } impl Store { /// Creates a `Ptr` that's a parent of two children - pub fn intern_2_ptrs(&mut self, tag: Tag, a: Ptr, b: Ptr) -> Ptr { - let (idx, inserted) = self.tuple2.insert_full((a, b)); + pub fn intern_2_ptrs(&self, tag: Tag, a: Ptr, b: Ptr) -> Ptr { + let (idx, inserted) = self.tuple2.insert_probe(Box::new((a, b))); let ptr = Ptr::Tuple2(tag, idx); if inserted { // this is for `hydrate_z_cache` - self.dehydrated.push(ptr); + self.dehydrated.load().push(Box::new(ptr)); } ptr } @@ -72,19 +73,19 @@ impl Store { /// Similar to `intern_2_ptrs` but doesn't add the resulting pointer to /// `dehydrated`. This function is used when converting a `ZStore` to a /// `Store`. - pub fn intern_2_ptrs_hydrated(&mut self, tag: Tag, a: Ptr, b: Ptr, z: ZPtr) -> Ptr { - let ptr = Ptr::Tuple2(tag, self.tuple2.insert_full((a, b)).0); + pub fn intern_2_ptrs_hydrated(&self, tag: Tag, a: Ptr, b: Ptr, z: ZPtr) -> Ptr { + let ptr = Ptr::Tuple2(tag, self.tuple2.insert_probe(Box::new((a, b))).0); self.z_cache.insert(ptr, Box::new(z)); ptr } /// Creates a `Ptr` that's a parent of three children - pub fn intern_3_ptrs(&mut self, tag: Tag, a: Ptr, b: Ptr, c: Ptr) -> Ptr { - let (idx, inserted) = self.tuple3.insert_full((a, b, c)); + pub fn intern_3_ptrs(&self, tag: Tag, a: Ptr, b: Ptr, c: Ptr) -> Ptr { + let (idx, inserted) = self.tuple3.insert_probe(Box::new((a, b, c))); let ptr = Ptr::Tuple3(tag, idx); if inserted { // this is for `hydrate_z_cache` - self.dehydrated.push(ptr); + self.dehydrated.load().push(Box::new(ptr)); } ptr } @@ -93,32 +94,25 @@ impl Store { /// `dehydrated`. This function is used when converting a `ZStore` to a /// `Store`. pub fn intern_3_ptrs_hydrated( - &mut self, + &self, tag: Tag, a: Ptr, b: Ptr, c: Ptr, z: ZPtr, ) -> Ptr { - let ptr = Ptr::Tuple3(tag, self.tuple3.insert_full((a, b, c)).0); + let ptr = Ptr::Tuple3(tag, self.tuple3.insert_probe(Box::new((a, b, c))).0); self.z_cache.insert(ptr, Box::new(z)); ptr } /// Creates a `Ptr` that's a parent of four children - pub fn intern_4_ptrs( - &mut self, - tag: Tag, - a: Ptr, - b: Ptr, - c: Ptr, - d: Ptr, - ) -> Ptr { - let (idx, inserted) = self.tuple4.insert_full((a, b, c, d)); + pub fn intern_4_ptrs(&self, tag: Tag, a: Ptr, b: Ptr, c: Ptr, d: Ptr) -> Ptr { + let (idx, inserted) = self.tuple4.insert_probe(Box::new((a, b, c, d))); let ptr = Ptr::Tuple4(tag, idx); if inserted { // this is for `hydrate_z_cache` - self.dehydrated.push(ptr); + self.dehydrated.load().push(Box::new(ptr)); } ptr } @@ -127,7 +121,7 @@ impl Store { /// `dehydrated`. This function is used when converting a `ZStore` to a /// `Store`. pub fn intern_4_ptrs_hydrated( - &mut self, + &self, tag: Tag, a: Ptr, b: Ptr, @@ -135,7 +129,7 @@ impl Store { d: Ptr, z: ZPtr, ) -> Ptr { - let ptr = Ptr::Tuple4(tag, self.tuple4.insert_full((a, b, c, d)).0); + let ptr = Ptr::Tuple4(tag, self.tuple4.insert_probe(Box::new((a, b, c, d))).0); self.z_cache.insert(ptr, Box::new(z)); ptr } @@ -155,24 +149,19 @@ impl Store { self.tuple4.get_index(idx) } - pub fn intern_string(&mut self, s: &str) -> Ptr { + pub fn intern_string(&self, s: &str) -> Ptr { if let Some(ptr) = self.string_ptr_cache.get(s) { *ptr } else { let ptr = s.chars().rev().fold(Ptr::null(Tag::Expr(Str)), |acc, c| { self.intern_2_ptrs(Tag::Expr(Str), Ptr::char(c), acc) }); - self.string_ptr_cache.insert(s.to_string(), ptr); + self.string_ptr_cache.insert(s.to_string(), Box::new(ptr)); self.ptr_string_cache.insert(ptr, s.to_string()); ptr } } - #[inline] - pub fn interned_string(&self, s: &str) -> Option<&Ptr> { - self.string_ptr_cache.get(s) - } - pub fn fetch_string(&self, ptr: &Ptr) -> Option { if let Some(str) = self.ptr_string_cache.get(ptr) { Some(str.to_string()) @@ -205,14 +194,14 @@ impl Store { } } - pub fn intern_symbol_path(&mut self, path: &[String]) -> Ptr { + pub fn intern_symbol_path(&self, path: &[String]) -> Ptr { path.iter().fold(Ptr::null(Tag::Expr(Sym)), |acc, s| { let s_ptr = self.intern_string(s); self.intern_2_ptrs(Tag::Expr(Sym), s_ptr, acc) }) } - pub fn intern_symbol(&mut self, sym: &Symbol) -> Ptr { + pub fn intern_symbol(&self, sym: &Symbol) -> Ptr { if let Some(ptr) = self.symbol_ptr_cache.get(sym) { *ptr } else { @@ -224,17 +213,12 @@ impl Store { } else { path_ptr }; - self.symbol_ptr_cache.insert(sym.clone(), sym_ptr); + self.symbol_ptr_cache.insert(sym.clone(), Box::new(sym_ptr)); self.ptr_symbol_cache.insert(sym_ptr, Box::new(sym.clone())); sym_ptr } } - #[inline] - pub fn interned_symbol(&self, s: &Symbol) -> Option<&Ptr> { - self.symbol_ptr_cache.get(s) - } - pub fn fetch_symbol_path(&self, mut idx: usize) -> Option> { let mut path = vec![]; loop { @@ -312,30 +296,28 @@ impl Store { } } - pub fn hide(&mut self, secret: F, payload: Ptr) -> Result> { + pub fn hide(&self, secret: F, payload: Ptr) -> Result> { let z_ptr = self.hash_ptr(&payload)?; let hash = self .poseidon_cache .hash3(&[secret, z_ptr.tag_field(), *z_ptr.value()]); - self.comms.insert(FWrap::(hash), (secret, payload)); + self.comms + .insert(FWrap::(hash), Box::new((secret, payload))); Ok(Ptr::comm(hash)) } - pub fn hide_and_return_z_payload( - &mut self, - secret: F, - payload: Ptr, - ) -> Result<(F, ZPtr)> { + pub fn hide_and_return_z_payload(&self, secret: F, payload: Ptr) -> Result<(F, ZPtr)> { let z_ptr = self.hash_ptr(&payload)?; let hash = self .poseidon_cache .hash3(&[secret, z_ptr.tag_field(), *z_ptr.value()]); - self.comms.insert(FWrap::(hash), (secret, payload)); + self.comms + .insert(FWrap::(hash), Box::new((secret, payload))); Ok((hash, z_ptr)) } #[inline] - pub fn commit(&mut self, payload: Ptr) -> Result> { + pub fn commit(&self, payload: Ptr) -> Result> { self.hide(F::NON_HIDING_COMMITMENT_SECRET, payload) } @@ -344,21 +326,21 @@ impl Store { } #[inline] - pub fn intern_lurk_sym(&mut self, name: &str) -> Ptr { + pub fn intern_lurk_sym(&self, name: &str) -> Ptr { self.intern_symbol(&lurk_sym(name)) } #[inline] - pub fn intern_nil(&mut self) -> Ptr { + pub fn intern_nil(&self) -> Ptr { self.intern_lurk_sym("nil") } #[inline] - pub fn key(&mut self, name: &str) -> Ptr { + pub fn key(&self, name: &str) -> Ptr { self.intern_symbol(&Symbol::key(&[name.to_string()])) } - pub fn car_cdr(&mut self, ptr: &Ptr) -> Result<(Ptr, Ptr)> { + pub fn car_cdr(&self, ptr: &Ptr) -> Result<(Ptr, Ptr)> { match ptr.tag() { Tag::Expr(Nil) => { let nil = self.intern_nil(); @@ -390,13 +372,13 @@ impl Store { } } - pub fn list(&mut self, elts: Vec>) -> Ptr { + pub fn list(&self, elts: Vec>) -> Ptr { elts.into_iter().rev().fold(self.intern_nil(), |acc, elt| { self.intern_2_ptrs(Tag::Expr(Cons), elt, acc) }) } - pub fn intern_syntax(&mut self, syn: Syntax) -> Ptr { + pub fn intern_syntax(&self, syn: Syntax) -> Ptr { match syn { Syntax::Num(_, x) => Ptr::Atom(Tag::Expr(Num), x.into_scalar()), Syntax::UInt(_, UInt::U64(x)) => Ptr::Atom(Tag::Expr(U64), x.into()), @@ -422,7 +404,7 @@ impl Store { } } - pub fn read(&mut self, state: Rc>, input: &str) -> Result> { + pub fn read(&self, state: Rc>, input: &str) -> Result> { match preceded( syntax::parse_space, syntax::parse_syntax(state, false, false), @@ -435,7 +417,7 @@ impl Store { } pub fn read_maybe_meta<'a>( - &mut self, + &self, state: Rc>, input: &'a str, ) -> Result<(Span<'a>, Ptr, bool), Error> { @@ -449,7 +431,7 @@ impl Store { } #[inline] - pub fn read_with_default_state(&mut self, input: &str) -> Result> { + pub fn read_with_default_state(&self, input: &str) -> Result> { self.read(State::init_lurk_state().rccell(), input) } @@ -553,11 +535,16 @@ impl Store { /// Hashes `Ptr` trees from the bottom to the top, avoiding deep recursions /// in `hash_ptr`. - pub fn hydrate_z_cache(&mut self) { - self.dehydrated.par_iter().for_each(|ptr| { - self.hash_ptr(ptr).expect("failed to hydrate pointer"); - }); - self.dehydrated = Vec::new(); + pub fn hydrate_z_cache(&self) { + self.dehydrated + .load() + .iter() + .collect::>() + .par_iter() + .for_each(|ptr| { + self.hash_ptr(ptr).expect("failed to hash_ptr"); + }); + self.dehydrated.swap(Arc::new(FrozenVec::default())); } pub fn to_vector(&self, ptrs: &[Ptr]) -> Result> { @@ -758,7 +745,7 @@ impl Ptr { }, Comm => match self.get_atom() { Some(f) => { - if store.comms.contains_key(&FWrap(*f)) { + if store.comms.get(&FWrap(*f)).is_some() { format!("(comm 0x{})", f.hex_digits()) } else { format!("", f.hex_digits()) diff --git a/src/lem/zstore.rs b/src/lem/zstore.rs index b74330080e..83e42e8027 100644 --- a/src/lem/zstore.rs +++ b/src/lem/zstore.rs @@ -120,7 +120,7 @@ pub fn populate_z_store( } pub fn populate_store( - store: &mut Store, + store: &Store, z_ptr: &ZPtr, z_store: &ZStore, ) -> Result> { diff --git a/src/lib.rs b/src/lib.rs index 00d6bb135a..e5476efc1f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,8 +1,5 @@ #![deny(unreachable_pub)] -#[macro_use] -extern crate alloc; -pub mod cache_map; #[macro_use] pub mod circuit; pub mod cli; diff --git a/src/proof/groth16.rs b/src/proof/groth16.rs index c5dbb34a25..4f8dafab4f 100644 --- a/src/proof/groth16.rs +++ b/src/proof/groth16.rs @@ -636,7 +636,7 @@ mod tests { let limit = 300; let lang = Lang::>::new(); - let (evaled, _, _) = Evaluator::new(fun_src, empty_sym_env(&s), &mut s, limit, &lang) + let (evaled, _, _) = Evaluator::new(fun_src, empty_sym_env(&s), &s, limit, &lang) .eval() .unwrap(); @@ -653,7 +653,7 @@ mod tests { let input = s.list(&[fun_from_comm, five]); let (output, _iterations, _emitted) = - Evaluator::new(input, empty_sym_env(&s), &mut s, limit, &lang) + Evaluator::new(input, empty_sym_env(&s), &s, limit, &lang) .eval() .unwrap(); diff --git a/src/proof/nova.rs b/src/proof/nova.rs index 1409c653bd..00f0f982b5 100644 --- a/src/proof/nova.rs +++ b/src/proof/nova.rs @@ -262,7 +262,7 @@ where frames: &[Frame, Witness, F, C>], store: &'a Store, lang: Arc>, - ) -> Result<(Proof<'_, F, C>, Vec, Vec, usize), ProofError> { + ) -> Result<(Proof<'a, F, C>, Vec, Vec, usize), ProofError> { let z0 = frames[0].input.to_vector(store)?; let zi = frames.last().unwrap().output.to_vector(store)?; let folding_config = Arc::new(FoldingConfig::new_ivc(lang.clone(), self.reduction_count())); diff --git a/src/repl.rs b/src/repl.rs index 95b7b44f9f..eaa2679014 100644 --- a/src/repl.rs +++ b/src/repl.rs @@ -333,7 +333,7 @@ impl> ReplState { pub fn eval_expr( &mut self, expr: Ptr, - store: &mut Store, + store: &Store, ) -> Result<(Ptr, usize, ContPtr, Vec>)> { let (io, iterations, emitted) = Evaluator::new(expr, self.env, store, self.limit, &self.lang).eval()?; diff --git a/src/store.rs b/src/store.rs index 0d5ccd87f8..53ad922971 100644 --- a/src/store.rs +++ b/src/store.rs @@ -1,12 +1,13 @@ -use rayon::prelude::*; -use std::collections::HashMap; +use arc_swap::ArcSwap; +use elsa::sync::{FrozenMap, FrozenVec}; +use elsa::sync_index_set::FrozenIndexSet; +use once_cell::sync::OnceCell; +use rayon::prelude::{IntoParallelRefIterator, ParallelIterator}; use std::fmt; +use std::sync::Arc; use std::usize; use thiserror; -use once_cell::sync::OnceCell; - -use crate::cache_map::CacheMap; use crate::cont::Continuation; use crate::expr; use crate::expr::{Expression, Thunk}; @@ -23,49 +24,49 @@ use crate::{Num, UInt}; use crate::hash::{HashConstants, InversePoseidonCache, PoseidonCache}; -type IndexSet = indexmap::IndexSet; +type IndexSet = FrozenIndexSet; #[derive(Debug)] pub struct Store { - pub cons_store: IndexSet<(Ptr, Ptr)>, - pub comm_store: IndexSet<(FWrap, Ptr)>, + pub cons_store: IndexSet, Ptr)>>, + pub comm_store: IndexSet, Ptr)>>, - pub fun_store: IndexSet<(Ptr, Ptr, Ptr)>, + pub fun_store: IndexSet, Ptr, Ptr)>>, /// Holds a Sym or Key which is a string head and a symbol tail - pub sym_store: IndexSet<(Ptr, Ptr)>, + pub sym_store: IndexSet, Ptr)>>, // Other sparse storage format without hashing is likely more efficient - pub num_store: IndexSet>, + pub num_store: IndexSet>>, /// Holds a Str, which is a char head and a string tail - pub str_store: IndexSet<(Ptr, Ptr)>, - pub thunk_store: IndexSet>, - pub call0_store: IndexSet<(Ptr, ContPtr)>, - pub call_store: IndexSet<(Ptr, Ptr, ContPtr)>, - pub call2_store: IndexSet<(Ptr, Ptr, ContPtr)>, - pub tail_store: IndexSet<(Ptr, ContPtr)>, - pub lookup_store: IndexSet<(Ptr, ContPtr)>, - pub unop_store: IndexSet<(Op1, ContPtr)>, - pub binop_store: IndexSet<(Op2, Ptr, Ptr, ContPtr)>, - pub binop2_store: IndexSet<(Op2, Ptr, ContPtr)>, - pub if_store: IndexSet<(Ptr, ContPtr)>, - pub let_store: IndexSet<(Ptr, Ptr, Ptr, ContPtr)>, - pub letrec_store: IndexSet<(Ptr, Ptr, Ptr, ContPtr)>, - pub emit_store: IndexSet>, + pub str_store: IndexSet, Ptr)>>, + pub thunk_store: IndexSet>>, + pub call0_store: IndexSet, ContPtr)>>, + pub call_store: IndexSet, Ptr, ContPtr)>>, + pub call2_store: IndexSet, Ptr, ContPtr)>>, + pub tail_store: IndexSet, ContPtr)>>, + pub lookup_store: IndexSet, ContPtr)>>, + pub unop_store: IndexSet)>>, + pub binop_store: IndexSet, Ptr, ContPtr)>>, + pub binop2_store: IndexSet, ContPtr)>>, + pub if_store: IndexSet, ContPtr)>>, + pub let_store: IndexSet, Ptr, Ptr, ContPtr)>>, + pub letrec_store: IndexSet, Ptr, Ptr, ContPtr)>>, + pub emit_store: IndexSet>>, /// Holds opaque pointers - pub opaque_ptrs: IndexSet>, + pub opaque_ptrs: IndexSet>>, /// Holds opaque continuation pointers - pub opaque_cont_ptrs: IndexSet>, + pub opaque_cont_ptrs: IndexSet>>, /// Holds a mapping of `ZExprPtr` -> `Ptr` for reverse lookups - pub z_expr_ptr_map: CacheMap, Box>>, + pub z_expr_ptr_map: FrozenMap, Box>>, /// Holds a mapping of `ZExprPtr` -> `ContPtr` for reverse lookups - pub z_cont_ptr_map: CacheMap, Box>>, + pub z_cont_ptr_map: FrozenMap, Box>>, - z_expr_ptr_cache: CacheMap, Box<(ZExprPtr, Option>)>>, - z_cont_ptr_cache: CacheMap, Box<(ZContPtr, Option>)>>, + z_expr_ptr_cache: FrozenMap, Box<(ZExprPtr, Option>)>>, + z_cont_ptr_cache: FrozenMap, Box<(ZContPtr, Option>)>>, /// Caches poseidon hashes pub poseidon_cache: PoseidonCache, @@ -73,18 +74,18 @@ pub struct Store { pub inverse_poseidon_cache: InversePoseidonCache, /// Contains Ptrs which have not yet been hydrated. - pub dehydrated: Vec>, - pub dehydrated_cont: Vec>, + pub dehydrated: ArcSwap>>>, + pub dehydrated_cont: ArcSwap>>>, - str_cache: HashMap>, - symbol_cache: HashMap>, + str_cache: FrozenMap>>, + symbol_cache: FrozenMap>>, pub constants: OnceCell>, } impl Default for Store { fn default() -> Self { - let mut store = Self { + let store = Self { cons_store: Default::default(), comm_store: Default::default(), sym_store: Default::default(), @@ -151,12 +152,12 @@ impl Store { } #[inline] - pub fn cons(&mut self, car: Ptr, cdr: Ptr) -> Ptr { + pub fn cons(&self, car: Ptr, cdr: Ptr) -> Ptr { self.intern_cons(car, cdr) } #[inline] - pub fn strcons(&mut self, car: Ptr, cdr: Ptr) -> Ptr { + pub fn strcons(&self, car: Ptr, cdr: Ptr) -> Ptr { self.intern_strcons(car, cdr) } @@ -172,15 +173,15 @@ impl Store { pub fn hidden(&self, secret: F, payload: Ptr) -> Option> { self.comm_store - .get_index_of(&(FWrap(secret), payload)) - .map(|c| Ptr::index(ExprTag::Comm, c)) + .get_full(&Box::new((FWrap(secret), payload))) + .map(|(c, _ref)| Ptr::index(ExprTag::Comm, c)) } - pub fn hide(&mut self, secret: F, payload: Ptr) -> Ptr { + pub fn hide(&self, secret: F, payload: Ptr) -> Ptr { self.intern_comm(secret, payload) } - pub fn commit(&mut self, payload: Ptr) -> Ptr { + pub fn commit(&self, payload: Ptr) -> Ptr { self.hide(F::NON_HIDING_COMMITMENT_SECRET, payload) } @@ -203,7 +204,7 @@ impl Store { .map(|(secret, payload)| (secret.0, *payload)) } - pub fn open_mut(&mut self, ptr: Ptr) -> Result<(F, Ptr), Error> { + pub fn open_mut(&self, ptr: Ptr) -> Result<(F, Ptr), Error> { let p = match ptr.tag { ExprTag::Comm => ptr, ExprTag::Num => { @@ -231,7 +232,7 @@ impl Store { .and_then(|(secret, _payload)| self.get_num(Num::Scalar(secret.0))) } - pub fn secret_mut(&mut self, ptr: Ptr) -> Result, Error> { + pub fn secret_mut(&self, ptr: Ptr) -> Result, Error> { let p = match ptr.tag { ExprTag::Comm => ptr, _ => return Err(Error("wrong type for commitment specifier".into())), @@ -246,7 +247,7 @@ impl Store { } } - pub fn list(&mut self, elts: &[Ptr]) -> Ptr { + pub fn list(&self, elts: &[Ptr]) -> Ptr { self.intern_list(elts) } @@ -254,19 +255,19 @@ impl Store { self.intern_num(num) } - pub fn uint64(&mut self, n: u64) -> Ptr { + pub fn uint64(&self, n: u64) -> Ptr { self.intern_u64(n) } - pub fn str(&mut self, s: &str) -> Ptr { + pub fn str(&self, s: &str) -> Ptr { self.intern_string(s) } - pub fn sym>(&mut self, name: T) -> Ptr { + pub fn sym>(&self, name: T) -> Ptr { self.intern_symbol(&Symbol::sym(&[name.as_ref()])) } - pub fn key>(&mut self, name: T) -> Ptr { + pub fn key>(&self, name: T) -> Ptr { self.intern_symbol(&Symbol::key(&[name.as_ref()])) } @@ -294,73 +295,75 @@ impl Store { } } - pub fn intern_cons(&mut self, car: Ptr, cdr: Ptr) -> Ptr { + pub fn intern_cons(&self, car: Ptr, cdr: Ptr) -> Ptr { if car.is_opaque() || cdr.is_opaque() { self.hash_expr(&car); self.hash_expr(&cdr); } - let (p, inserted) = self.cons_store.insert_full((car, cdr)); + let (p, inserted) = self.cons_store.insert_probe(Box::new((car, cdr))); let ptr = Ptr::index(ExprTag::Cons, p); if inserted { - self.dehydrated.push(ptr); + self.dehydrated.load().push(Box::new(ptr)); } ptr } - pub fn intern_strcons(&mut self, car: Ptr, cdr: Ptr) -> Ptr { + pub fn intern_strcons(&self, car: Ptr, cdr: Ptr) -> Ptr { if car.is_opaque() || cdr.is_opaque() { self.hash_expr(&car); self.hash_expr(&cdr); } assert_eq!((car.tag, cdr.tag), (ExprTag::Char, ExprTag::Str)); - let (i, _) = self.str_store.insert_full((car, cdr)); + let (i, _) = self.str_store.insert_probe(Box::new((car, cdr))); Ptr::index(ExprTag::Str, i) } - pub fn intern_symcons(&mut self, car: Ptr, cdr: Ptr) -> Ptr { + pub fn intern_symcons(&self, car: Ptr, cdr: Ptr) -> Ptr { if car.is_opaque() || cdr.is_opaque() { self.hash_expr(&car); self.hash_expr(&cdr); } assert_eq!((car.tag, cdr.tag), (ExprTag::Str, ExprTag::Sym)); - let (i, _) = self.sym_store.insert_full((car, cdr)); + let (i, _) = self.sym_store.insert_probe(Box::new((car, cdr))); Ptr::index(ExprTag::Sym, i) } - pub fn intern_keycons(&mut self, car: Ptr, cdr: Ptr) -> Ptr { + pub fn intern_keycons(&self, car: Ptr, cdr: Ptr) -> Ptr { if car.is_opaque() || cdr.is_opaque() { self.hash_expr(&car); self.hash_expr(&cdr); } assert_eq!((car.tag, cdr.tag), (ExprTag::Str, ExprTag::Sym)); - let (i, _) = self.sym_store.insert_full((car, cdr)); + let (i, _) = self.sym_store.insert_probe(Box::new((car, cdr))); Ptr::index(ExprTag::Key, i) } - pub fn intern_comm(&mut self, secret: F, payload: Ptr) -> Ptr { + pub fn intern_comm(&self, secret: F, payload: Ptr) -> Ptr { if payload.is_opaque() { self.hash_expr(&payload); } - let (p, inserted) = self.comm_store.insert_full((FWrap(secret), payload)); + let (p, inserted) = self + .comm_store + .insert_probe(Box::new((FWrap(secret), payload))); let ptr = Ptr::index(ExprTag::Comm, p); if inserted { - self.dehydrated.push(ptr); + self.dehydrated.load().push(Box::new(ptr)); } ptr } // Intern a potentially-opaque value. If the corresponding value is already known to the store, // return the known value. - pub fn intern_maybe_opaque(&mut self, tag: ExprTag, hash: F) -> Ptr { + pub fn intern_maybe_opaque(&self, tag: ExprTag, hash: F) -> Ptr { self.intern_opaque_aux(tag, hash, true) } // Intern an opaque value. If the corresponding non-opaque value is already known to the store, // return an opaque one anyway. - fn intern_opaque(&mut self, tag: ExprTag, hash: F) -> Ptr { + fn intern_opaque(&self, tag: ExprTag, hash: F) -> Ptr { self.intern_opaque_aux(tag, hash, false) } @@ -377,7 +380,7 @@ impl Store { // Intern a potentially-opaque value. If the corresponding non-opaque value is already known to the store, and // `return_non_opaque_if_existing` is true, return the known value. fn intern_opaque_aux( - &mut self, + &self, tag: ExprTag, hash: F, return_non_opaque_if_existing: bool, @@ -395,44 +398,44 @@ impl Store { } } - let (i, _) = self.opaque_ptrs.insert_full(z_ptr); + let (i, _) = self.opaque_ptrs.insert_probe(Box::new(z_ptr)); Ptr::opaque(tag, i) } - pub fn intern_maybe_opaque_fun(&mut self, hash: F) -> Ptr { + pub fn intern_maybe_opaque_fun(&self, hash: F) -> Ptr { self.intern_maybe_opaque(ExprTag::Fun, hash) } - pub fn intern_maybe_opaque_sym(&mut self, hash: F) -> Ptr { + pub fn intern_maybe_opaque_sym(&self, hash: F) -> Ptr { self.intern_maybe_opaque(ExprTag::Sym, hash) } - pub fn intern_maybe_opaque_cons(&mut self, hash: F) -> Ptr { + pub fn intern_maybe_opaque_cons(&self, hash: F) -> Ptr { self.intern_maybe_opaque(ExprTag::Cons, hash) } - pub fn intern_maybe_opaque_comm(&mut self, hash: F) -> Ptr { + pub fn intern_maybe_opaque_comm(&self, hash: F) -> Ptr { self.intern_maybe_opaque(ExprTag::Comm, hash) } - pub fn intern_opaque_fun(&mut self, hash: F) -> Ptr { + pub fn intern_opaque_fun(&self, hash: F) -> Ptr { self.intern_opaque(ExprTag::Fun, hash) } - pub fn intern_opaque_sym(&mut self, hash: F) -> Ptr { + pub fn intern_opaque_sym(&self, hash: F) -> Ptr { self.intern_opaque(ExprTag::Sym, hash) } - pub fn intern_opaque_cons(&mut self, hash: F) -> Ptr { + pub fn intern_opaque_cons(&self, hash: F) -> Ptr { self.intern_opaque(ExprTag::Cons, hash) } - pub fn intern_opaque_comm(&mut self, hash: F) -> Ptr { + pub fn intern_opaque_comm(&self, hash: F) -> Ptr { self.intern_opaque(ExprTag::Comm, hash) } /// Helper to allocate a list, instead of manually using `cons`. - pub fn intern_list(&mut self, elts: &[Ptr]) -> Ptr { + pub fn intern_list(&self, elts: &[Ptr]) -> Ptr { elts.iter() .rev() .fold(lurk_sym_ptr!(self, nil), |acc, elt| { @@ -440,14 +443,14 @@ impl Store { }) } - pub fn intern_symbol_path(&mut self, path: &[String]) -> Ptr { + pub fn intern_symbol_path(&self, path: &[String]) -> Ptr { path.iter().fold(self.symnil(), |acc, s| { let s_ptr = self.intern_string(s); self.intern_symcons(s_ptr, acc) }) } - pub fn intern_symbol(&mut self, sym: &Symbol) -> Ptr { + pub fn intern_symbol(&self, sym: &Symbol) -> Ptr { match self.symbol_cache.get(sym) { Some(ptr) => *ptr, None => { @@ -460,17 +463,17 @@ impl Store { } else { path_ptr }; - self.symbol_cache.insert(sym.clone(), sym_ptr); + self.symbol_cache.insert(sym.clone(), Box::new(sym_ptr)); sym_ptr } } } - pub fn user_sym(&mut self, name: &str) -> Ptr { + pub fn user_sym(&self, name: &str) -> Ptr { self.intern_symbol(&user_sym(name)) } - pub fn intern_num>>(&mut self, num: T) -> Ptr { + pub fn intern_num>>(&self, num: T) -> Ptr { let num = num.into(); let num = match num { Num::Scalar(scalar) => { @@ -482,7 +485,7 @@ impl Store { } Num::U64(_) => num, }; - let (ptr, _) = self.num_store.insert_full(num); + let (ptr, _) = self.num_store.insert_probe(Box::new(num)); Ptr::index(ExprTag::Num, ptr) } @@ -501,8 +504,8 @@ impl Store { }; self.num_store - .get_index_of::>(&num) - .map(|x| Ptr::index(ExprTag::Num, x)) + .get_full(&num) + .map(|(x, _)| Ptr::index(ExprTag::Num, x)) } #[inline] @@ -520,41 +523,43 @@ impl Store { Ptr::index(ExprTag::U64, n as usize) } - pub fn intern_string(&mut self, s: &str) -> Ptr { + pub fn intern_string(&self, s: &str) -> Ptr { match self.str_cache.get(s) { Some(ptr) => *ptr, None => { let ptr = s.chars().rev().fold(self.strnil(), |acc, c| { self.intern_strcons(self.intern_char(c), acc) }); - self.str_cache.insert(s.to_string(), ptr); + self.str_cache.insert(s.to_string(), Box::new(ptr)); ptr } } } - pub fn intern_fun(&mut self, arg: Ptr, body: Ptr, closed_env: Ptr) -> Ptr { + pub fn intern_fun(&self, arg: Ptr, body: Ptr, closed_env: Ptr) -> Ptr { // TODO: closed_env must be an env assert!(matches!(arg.tag, ExprTag::Sym), "ARG must be a symbol"); - let (p, inserted) = self.fun_store.insert_full((arg, body, closed_env)); + let (p, inserted) = self + .fun_store + .insert_probe(Box::new((arg, body, closed_env))); let ptr = Ptr::index(ExprTag::Fun, p); if inserted { - self.dehydrated.push(ptr); + self.dehydrated.load().push(Box::new(ptr)); } ptr } - pub fn intern_thunk(&mut self, thunk: Thunk) -> Ptr { - let (p, inserted) = self.thunk_store.insert_full(thunk); + pub fn intern_thunk(&self, thunk: Thunk) -> Ptr { + let (p, inserted) = self.thunk_store.insert_probe(Box::new(thunk)); let ptr = Ptr::index(ExprTag::Thunk, p); if inserted { - self.dehydrated.push(ptr); + self.dehydrated.load().push(Box::new(ptr)); } ptr } - pub fn mark_dehydrated_cont(&mut self, p: ContPtr) -> ContPtr { - self.dehydrated_cont.push(p); + pub fn mark_dehydrated_cont(&self, p: ContPtr) -> ContPtr { + self.dehydrated_cont.load().push(Box::new(p)); p } @@ -590,19 +595,19 @@ impl Store { ]) } - pub fn intern_cont_error(&mut self) -> ContPtr { + pub fn intern_cont_error(&self) -> ContPtr { self.mark_dehydrated_cont(self.get_cont_error()) } - pub fn intern_cont_outermost(&mut self) -> ContPtr { + pub fn intern_cont_outermost(&self) -> ContPtr { self.mark_dehydrated_cont(self.get_cont_outermost()) } - pub fn intern_cont_terminal(&mut self) -> ContPtr { + pub fn intern_cont_terminal(&self) -> ContPtr { self.mark_dehydrated_cont(self.get_cont_terminal()) } - pub fn intern_cont_dummy(&mut self) -> ContPtr { + pub fn intern_cont_dummy(&self) -> ContPtr { self.mark_dehydrated_cont(self.get_cont_dummy()) } @@ -1278,14 +1283,14 @@ impl Store { self.get_z_cont(ptr, &mut None).ok().map(|x| x.0) } - pub fn hash_string(&mut self, s: &str) -> ZExprPtr { + pub fn hash_string(&self, s: &str) -> ZExprPtr { let ptr = self.intern_string(s); self.get_z_expr(&ptr, &mut None) .expect("known string can't be opaque") .0 } - pub fn hash_symbol(&mut self, s: &Symbol) -> ZExprPtr { + pub fn hash_symbol(&self, s: &Symbol) -> ZExprPtr { let ptr = self.intern_symbol(s); self.get_z_expr(&ptr, &mut None) .expect("known symbol can't be opaque") @@ -1318,12 +1323,12 @@ impl Store { // An opaque Ptr is one for which we have the hash, but not the preimages. // So we cannot open or traverse the enclosed data, but we can manipulate // it atomically and include it in containing structures, etc. - pub fn new_opaque_ptr(&mut self) -> Ptr { + pub fn new_opaque_ptr(&self) -> Ptr { // TODO: May need new tag for this. // Meanwhile, it is illegal to try to dereference/follow an opaque PTR. // So any tag and RawPtr are okay. let z_ptr = ZExpr::Nil.z_ptr(&self.poseidon_cache); - let (i, _) = self.opaque_ptrs.insert_full(z_ptr); + let (i, _) = self.opaque_ptrs.insert_probe(Box::new(z_ptr)); Ptr::opaque(ExprTag::Nil, i) } @@ -1355,25 +1360,33 @@ impl Store { /// safe to call this incrementally. However, for best proving performance, we should call exactly once so all /// hashing can be batched, e.g. on the GPU. #[tracing::instrument(skip_all, name = "Store::hydrate_scalar_cache")] - pub fn hydrate_scalar_cache(&mut self) { + pub fn hydrate_scalar_cache(&self) { self.ensure_constants(); - self.dehydrated.par_iter().for_each(|ptr| { - self.hash_expr(ptr).expect("failed to hash_expr"); - }); + self.dehydrated + .load() + .iter() + .collect::>() + .par_iter() + .for_each(|ptr| { + self.hash_expr(ptr).expect("failed to hash_expr"); + }); - self.dehydrated.truncate(0); + self.dehydrated.swap(Arc::new(FrozenVec::default())); - self.dehydrated_cont.par_iter().for_each(|ptr| { - self.hash_cont(ptr).expect("failed to hash_cont"); - }); + self.dehydrated_cont + .load() + .iter() + .collect::>() + .par_iter() + .for_each(|ptr| { + self.hash_cont(ptr).expect("failed to hash_cont"); + }); - self.dehydrated_cont.truncate(0); - - self.dehydrated_cont.clear(); + self.dehydrated_cont.swap(Arc::new(FrozenVec::default())); } - fn ensure_constants(&mut self) { + fn ensure_constants(&self) { if self.constants.get().is_none() { let new = NamedConstants::new(self); self.constants.set(new).expect("constants are not set"); @@ -1408,11 +1421,7 @@ impl Store { } } - pub fn intern_z_expr_ptr( - &mut self, - z_ptr: &ZExprPtr, - z_store: &ZStore, - ) -> Option> { + pub fn intern_z_expr_ptr(&self, z_ptr: &ZExprPtr, z_store: &ZStore) -> Option> { if let Some(ptr) = self.fetch_z_expr_ptr(z_ptr) { Some(ptr) } else { @@ -1526,7 +1535,7 @@ impl Store { } pub fn intern_z_cont_ptr( - &mut self, + &self, z_ptr: &ZContPtr, z_store: &ZStore, ) -> Option> { @@ -1744,11 +1753,11 @@ pub struct NamedConstants { } impl NamedConstants { - pub fn new(store: &mut Store) -> Self { + pub fn new(store: &Store) -> Self { let nil_ptr = store.intern_symbol(&lurk_sym("nil")); let nil_z_ptr = Some(ZExpr::Nil.z_ptr(&store.poseidon_cache)); - let mut hash_sym = |name: &str| { + let hash_sym = |name: &str| { let ptr = store.intern_symbol(&lurk_sym(name)); let maybe_z_ptr = store.hash_expr(&ptr); ConstantPtrs(maybe_z_ptr, ptr) @@ -1834,7 +1843,7 @@ impl NamedConstants { impl ZStore { pub fn to_store(&self) -> Store { - let mut store = Store::new(); + let store = Store::new(); for ptr in self.expr_map.keys() { store.intern_z_expr_ptr(ptr, self); @@ -1846,7 +1855,7 @@ impl ZStore { } pub fn to_store_with_z_ptr(&self, z_ptr: &ZExprPtr) -> Result<(Store, Ptr), Error> { - let mut store = Store::new(); + let store = Store::new(); for z_ptr in self.expr_map.keys() { store.intern_z_expr_ptr(z_ptr, self); @@ -1975,26 +1984,23 @@ pub mod test { let lang: Lang> = Lang::new(); { let comparison_expr = store.list(&[eq, fun, opaque_fun]); - let (result, _, _) = - Evaluator::new(comparison_expr, empty_env, &mut store, limit, &lang) - .eval() - .unwrap(); + let (result, _, _) = Evaluator::new(comparison_expr, empty_env, &store, limit, &lang) + .eval() + .unwrap(); assert_eq!(t, result.expr); } { let comparison_expr = store.list(&[eq, fun2, opaque_fun]); - let (result, _, _) = - Evaluator::new(comparison_expr, empty_env, &mut store, limit, &lang) - .eval() - .unwrap(); + let (result, _, _) = Evaluator::new(comparison_expr, empty_env, &store, limit, &lang) + .eval() + .unwrap(); assert_eq!(nil, result.expr); } { let comparison_expr = store.list(&[eq, fun2, opaque_fun2]); - let (result, _, _) = - Evaluator::new(comparison_expr, empty_env, &mut store, limit, &lang) - .eval() - .unwrap(); + let (result, _, _) = Evaluator::new(comparison_expr, empty_env, &store, limit, &lang) + .eval() + .unwrap(); assert_eq!(t, result.expr); } { @@ -2007,10 +2013,9 @@ pub mod test { let cons_expr2 = store.list(&[cons, opaque_fun, n]); let comparison_expr = store.list(&[eq, cons_expr1, cons_expr2]); - let (result, _, _) = - Evaluator::new(comparison_expr, empty_env, &mut store, limit, &lang) - .eval() - .unwrap(); + let (result, _, _) = Evaluator::new(comparison_expr, empty_env, &store, limit, &lang) + .eval() + .unwrap(); assert_eq!(t, result.expr); } } @@ -2051,7 +2056,7 @@ pub mod test { // For now, all opaque data remains opaque, even if the Store has enough information to clarify it. assert!(sym.fmt_to_string(&store, state) != opaque_sym.fmt_to_string(&store, state)); - let mut other_store = Store::::default(); + let other_store = Store::::default(); let other_opaque_sym = other_store.intern_opaque_sym(*sym_hash.value()); let other_sym = other_store.sym("sym"); @@ -2079,26 +2084,23 @@ pub mod test { let lang = Lang::>::new(); { let comparison_expr = store.list(&[eq, qsym, qsym_opaque]); - let (result, _, _) = - Evaluator::new(comparison_expr, empty_env, &mut store, limit, &lang) - .eval() - .unwrap(); + let (result, _, _) = Evaluator::new(comparison_expr, empty_env, &store, limit, &lang) + .eval() + .unwrap(); assert_eq!(t, result.expr); } { let comparison_expr = store.list(&[eq, qsym2, qsym_opaque]); - let (result, _, _) = - Evaluator::new(comparison_expr, empty_env, &mut store, limit, &lang) - .eval() - .unwrap(); + let (result, _, _) = Evaluator::new(comparison_expr, empty_env, &store, limit, &lang) + .eval() + .unwrap(); assert_eq!(nil, result.expr); } { let comparison_expr = store.list(&[eq, qsym2, qsym_opaque2]); - let (result, _, _) = - Evaluator::new(comparison_expr, empty_env, &mut store, limit, &lang) - .eval() - .unwrap(); + let (result, _, _) = Evaluator::new(comparison_expr, empty_env, &store, limit, &lang) + .eval() + .unwrap(); assert_eq!(t, result.expr); } { @@ -2112,10 +2114,9 @@ pub mod test { let comparison_expr = store.list(&[eq, cons_expr1, cons_expr2]); let lang: Lang> = Lang::new(); - let (result, _, _) = - Evaluator::new(comparison_expr, empty_env, &mut store, limit, &lang) - .eval() - .unwrap(); + let (result, _, _) = Evaluator::new(comparison_expr, empty_env, &store, limit, &lang) + .eval() + .unwrap(); assert_eq!(t, result.expr); } } @@ -2156,26 +2157,23 @@ pub mod test { { let comparison_expr = store.list(&[eq, qcons, qcons_opaque]); - let (result, _, _) = - Evaluator::new(comparison_expr, empty_env, &mut store, limit, &lang) - .eval() - .unwrap(); + let (result, _, _) = Evaluator::new(comparison_expr, empty_env, &store, limit, &lang) + .eval() + .unwrap(); assert_eq!(t, result.expr); } { let comparison_expr = store.list(&[eq, qcons2, qcons_opaque]); - let (result, _, _) = - Evaluator::new(comparison_expr, empty_env, &mut store, limit, &lang) - .eval() - .unwrap(); + let (result, _, _) = Evaluator::new(comparison_expr, empty_env, &store, limit, &lang) + .eval() + .unwrap(); assert_eq!(nil, result.expr); } { let comparison_expr = store.list(&[eq, qcons2, qcons_opaque2]); - let (result, _, _) = - Evaluator::new(comparison_expr, empty_env, &mut store, limit, &lang) - .eval() - .unwrap(); + let (result, _, _) = Evaluator::new(comparison_expr, empty_env, &store, limit, &lang) + .eval() + .unwrap(); assert_eq!(t, result.expr); } { @@ -2195,14 +2193,14 @@ pub mod test { let lang: Lang> = Lang::new(); { let (result, _, _) = - Evaluator::new(comparison_expr, empty_env, &mut store, limit, &lang) + Evaluator::new(comparison_expr, empty_env, &store, limit, &lang) .eval() .unwrap(); assert_eq!(t, result.expr); } { let (result, _, _) = - Evaluator::new(comparison_expr2, empty_env, &mut store, limit, &lang) + Evaluator::new(comparison_expr2, empty_env, &store, limit, &lang) .eval() .unwrap(); assert_eq!(nil, result.expr); diff --git a/src/syntax.rs b/src/syntax.rs index 6553df92cd..db20b5913d 100644 --- a/src/syntax.rs +++ b/src/syntax.rs @@ -189,7 +189,7 @@ mod test { #[test] fn display_syntax() { - let mut s = Store::::default(); + let s = Store::::default(); macro_rules! improper { ( $( $x:expr ),+ ) => { diff --git a/src/writer.rs b/src/writer.rs index c221bf9c90..da6c014780 100644 --- a/src/writer.rs +++ b/src/writer.rs @@ -384,7 +384,7 @@ pub mod test { #[test] fn test_print_keyword() { - let mut store = Store::::default(); + let store = Store::::default(); let foo_key_ptr = store.intern_symbol(&Symbol::key_from_vec(vec!["foo".into()])); let foo_key_str = foo_key_ptr.fmt_to_string(&store, initial_lurk_state()); assert_eq!(":foo", foo_key_str); diff --git a/src/z_data/z_store.rs b/src/z_data/z_store.rs index 0aab5e4650..3e92f2aa42 100644 --- a/src/z_data/z_store.rs +++ b/src/z_data/z_store.rs @@ -51,7 +51,7 @@ impl ZStore { /// Converts an entire store to a `ZStore` /// WARNING: This will leak secrets used for opaque data in /// `Store::comm_store`. Not for use with hiding commitments - pub fn to_z_store(store: &mut Store) -> Self { + pub fn to_z_store(store: &Store) -> Self { store.hydrate_scalar_cache(); let mut zstore = ZStore::new(); for zptr in store.z_expr_ptr_map.keys_cloned() {