Skip to content

Commit

Permalink
feat: Add hash set implementation which can be stored as account
Browse files Browse the repository at this point in the history
We want to use hash sets as queues for nullifiers and address spaces.
However, the `std` and `hashbrown` implementations are dynamically
allocated and resized, which doesn't serve our purpose of storing the
underlying data as Solana account.

Therefore, we implement our own hash set with the following properties:

* [Quadratic probing](https://en.wikipedia.org/wiki/Quadratic_probing)
  as a solution for hash collisions.
* Load factor 0.7 (70%) - which means that the size of the structure
  always includes at least 70% of additional space (more than expected
  elements) for efficiency.
* The final size is a prime number greather than the size of elements
  and size determined by low factor. To find the prime number, we probe
  6k + 1 and 6k + 5 candidates. We check whether they are prime in a
  brute-force way, because we want to be sure there are no false
  positives.
  • Loading branch information
vadorovsky committed Apr 3, 2024
1 parent 47269c3 commit fad346b
Show file tree
Hide file tree
Showing 38 changed files with 2,849 additions and 1,470 deletions.
24 changes: 24 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

13 changes: 6 additions & 7 deletions circuit-lib/circuitlib-rs/src/init_merkle_tree.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
use std::sync::Mutex;

use ark_ff::{BigInteger, BigInteger256};
use ark_std::Zero;
use light_hasher::{Hasher, Poseidon};
use light_indexed_merkle_tree::{array::IndexingArray, reference::IndexedMerkleTree};
use light_indexed_merkle_tree::{array::IndexedArray, reference::IndexedMerkleTree};
use light_merkle_tree_reference::MerkleTree;
use log::info;
use num_bigint::{BigInt, Sign};
use num_bigint::{BigInt, Sign, ToBigUint};
use once_cell::{self, sync::Lazy};

use crate::{
Expand Down Expand Up @@ -73,10 +72,10 @@ pub fn non_inclusion_merkle_tree_inputs_26() -> NonInclusionMerkleProofInputs {
const ROOTS: usize = 1;
const CANOPY: usize = 0;
let mut indexed_tree =
IndexedMerkleTree::<Poseidon, usize, BigInteger256>::new(HEIGHT, ROOTS, CANOPY).unwrap();
let mut indexing_array = IndexingArray::<Poseidon, usize, BigInteger256, 1024>::default();
IndexedMerkleTree::<Poseidon, usize>::new(HEIGHT, ROOTS, CANOPY).unwrap();
let mut indexing_array = IndexedArray::<Poseidon, usize, 1024>::default();

let bundle1 = indexing_array.append(BigInteger256::from(1_u32)).unwrap();
let bundle1 = indexing_array.append(&1_u32.to_biguint().unwrap()).unwrap();
indexed_tree
.update(
&bundle1.new_low_element,
Expand All @@ -85,7 +84,7 @@ pub fn non_inclusion_merkle_tree_inputs_26() -> NonInclusionMerkleProofInputs {
)
.unwrap();

let bundle3 = indexing_array.append(BigInteger256::from(3_u32)).unwrap();
let bundle3 = indexing_array.append(&3_u32.to_biguint().unwrap()).unwrap();
indexed_tree
.update(
&bundle3.new_low_element,
Expand Down

Large diffs are not rendered by default.

Large diffs are not rendered by default.

7 changes: 3 additions & 4 deletions merkle-tree/concurrent/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -504,14 +504,13 @@ where
///
/// # Purpose
///
/// This method is meant to be used mostly in Solana programs, where memory
/// constraints are tight and we want to make sure no data is copied.
/// This method is meant to be used mostly in Solana programs to initialize
/// a new account which is supposed to store the Merkle tree.
///
/// # Safety
///
/// This is highly unsafe. This method validates only sizes of slices.
/// Ensuring the alignment and that the slices provide actual data of the
/// Merkle tree is the caller's responsibility.
/// Ensuring the alignment is the caller's responsibility.
///
/// Calling it in async context (or anywhere where the underlying data can
/// be moved in the memory) is certainly going to cause undefined behavior.
Expand Down
21 changes: 21 additions & 0 deletions merkle-tree/hash-set/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
[package]
name = "light-hash-set"
version = "0.1.0"
edition = "2021"

[features]
solana = ["solana-program"]

[dependencies]
light-bounded-vec = { path = "../bounded-vec" }
light-utils = { path = "../../utils" }
memoffset = "0.9"
num-bigint = "0.4"
num-traits = "0.2"
solana-program = { version = ">=1.17, <1.18", optional = true }
thiserror = "1.0"

[dev-dependencies]
ark-bn254 = "0.4"
ark-ff = "0.4"
rand = "0.8"
Loading

0 comments on commit fad346b

Please sign in to comment.