feat(rln): ability to pass rln tree config in ffi (#150)

* feat(rln): pass config in rln ffi

* fix: for rln-wasm

* fix: ffi tests

* fix: clippy

* fix: test cursor
This commit is contained in:
Aaryamann Challani 2023-05-05 15:15:33 +05:30 committed by GitHub
parent c4b699ddff
commit 2c4b399126
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 150 additions and 39 deletions

2
Cargo.lock generated
View File

@ -2395,6 +2395,7 @@ dependencies = [
"once_cell", "once_cell",
"rand", "rand",
"rand_chacha", "rand_chacha",
"serde",
"serde_json", "serde_json",
"sled", "sled",
"thiserror", "thiserror",
@ -3117,6 +3118,7 @@ dependencies = [
"num-bigint", "num-bigint",
"num-traits", "num-traits",
"pmtree", "pmtree",
"serde",
"sled", "sled",
"tiny-keccak", "tiny-keccak",
] ]

View File

@ -41,6 +41,7 @@ utils = { path = "../utils/", default-features = false }
# serialization # serialization
serde_json = "1.0.48" serde_json = "1.0.48"
serde = { version = "1.0.130", features = ["derive"] }
include_dir = "=0.7.3" include_dir = "=0.7.3"

View File

@ -2,7 +2,10 @@ use crate::circuit::Fr;
use crate::hashers::{poseidon_hash, PoseidonHash}; use crate::hashers::{poseidon_hash, PoseidonHash};
use crate::utils::{bytes_le_to_fr, fr_to_bytes_le}; use crate::utils::{bytes_le_to_fr, fr_to_bytes_le};
use color_eyre::{Report, Result}; use color_eyre::{Report, Result};
use serde_json::Value;
use std::fmt::Debug; use std::fmt::Debug;
use std::path::PathBuf;
use std::str::FromStr;
use utils::*; use utils::*;
pub struct PmTree { pub struct PmTree {
@ -37,10 +40,39 @@ impl pmtree::Hasher for PoseidonHash {
} }
} }
fn get_tmp_path() -> std::path::PathBuf {
std::env::temp_dir().join(format!("pmtree-{}", rand::random::<u64>()))
}
fn get_tmp() -> bool {
true
}
pub struct PmtreeConfig(pm_tree::Config); pub struct PmtreeConfig(pm_tree::Config);
impl FromStr for PmtreeConfig {
type Err = Report;
fn from_str(s: &str) -> Result<Self> {
let config: Value = serde_json::from_str(s)?;
let temporary = config["temporary"].as_bool();
let path = config["path"].as_str();
let path = match path {
Some(path) => Some(PathBuf::from(path)),
None => None,
};
let config = pm_tree::Config::new()
.temporary(temporary.unwrap_or(get_tmp()))
.path(path.unwrap_or(get_tmp_path()));
Ok(PmtreeConfig(config))
}
}
impl Default for PmtreeConfig { impl Default for PmtreeConfig {
fn default() -> Self { fn default() -> Self {
let tmp_path = std::env::temp_dir().join(format!("pmtree-{}", rand::random::<u64>())); let tmp_path = get_tmp_path();
PmtreeConfig(pm_tree::Config::new().temporary(true).path(tmp_path)) PmtreeConfig(pm_tree::Config::new().temporary(true).path(tmp_path))
} }
} }

View File

@ -12,8 +12,10 @@ use ark_serialize::{CanonicalDeserialize, CanonicalSerialize, Read, Write};
use cfg_if::cfg_if; use cfg_if::cfg_if;
use color_eyre::{Report, Result}; use color_eyre::{Report, Result};
use num_bigint::BigInt; use num_bigint::BigInt;
use serde_json::{json, Value};
use std::io::Cursor; use std::io::Cursor;
use utils::{ZerokitMerkleProof, ZerokitMerkleTree}; use std::str::FromStr;
use utils::{Hasher, ZerokitMerkleProof, ZerokitMerkleTree};
cfg_if! { cfg_if! {
if #[cfg(not(target_arch = "wasm32"))] { if #[cfg(not(target_arch = "wasm32"))] {
@ -62,7 +64,7 @@ impl RLN<'_> {
/// use std::io::Cursor; /// use std::io::Cursor;
/// ///
/// let tree_height = 20; /// let tree_height = 20;
/// let resources = Cursor::new("tree_height_20"); /// let resources = Cursor::new(json!({"resources_folder": "tree_height_20"});
/// ///
/// // We create a new RLN instance /// // We create a new RLN instance
/// let mut rln = RLN::new(tree_height, resources); /// let mut rln = RLN::new(tree_height, resources);
@ -73,15 +75,30 @@ impl RLN<'_> {
let mut input: Vec<u8> = Vec::new(); let mut input: Vec<u8> = Vec::new();
input_data.read_to_end(&mut input)?; input_data.read_to_end(&mut input)?;
let resources_folder = String::from_utf8(input)?; let rln_config: Value = serde_json::from_str(&String::from_utf8(input)?)?;
let resources_folder = rln_config["resources_folder"]
.as_str()
.unwrap_or(TEST_RESOURCES_FOLDER);
let tree_config_opt = rln_config["tree_config"].as_str();
let witness_calculator = circom_from_folder(&resources_folder)?; let witness_calculator = circom_from_folder(resources_folder)?;
let proving_key = zkey_from_folder(&resources_folder)?; let proving_key = zkey_from_folder(resources_folder)?;
let verification_key = vk_from_folder(&resources_folder)?; let verification_key = vk_from_folder(resources_folder)?;
let tree_config: <PoseidonTree as ZerokitMerkleTree>::Config = match tree_config_opt {
Some(tree_config_str) => {
<PoseidonTree as ZerokitMerkleTree>::Config::from_str(tree_config_str)?
}
None => <PoseidonTree as ZerokitMerkleTree>::Config::default(),
};
// We compute a default empty tree // We compute a default empty tree
let tree = PoseidonTree::default(tree_height)?; let tree = PoseidonTree::new(
tree_height,
<PoseidonTree as ZerokitMerkleTree>::Hasher::default_leaf(),
tree_config,
)?;
Ok(RLN { Ok(RLN {
witness_calculator, witness_calculator,
@ -990,7 +1007,7 @@ impl RLN<'_> {
impl Default for RLN<'_> { impl Default for RLN<'_> {
fn default() -> Self { fn default() -> Self {
let tree_height = TEST_TREE_HEIGHT; let tree_height = TEST_TREE_HEIGHT;
let buffer = Cursor::new(TEST_RESOURCES_FOLDER); let buffer = Cursor::new(json!({ "resources_folder": TEST_RESOURCES_FOLDER }).to_string());
Self::new(tree_height, buffer).unwrap() Self::new(tree_height, buffer).unwrap()
} }
} }
@ -1066,6 +1083,7 @@ mod test {
use super::*; use super::*;
use ark_std::{rand::thread_rng, UniformRand}; use ark_std::{rand::thread_rng, UniformRand};
use rand::Rng; use rand::Rng;
use serde_json::json;
use utils::ZerokitMerkleTree; use utils::ZerokitMerkleTree;
#[test] #[test]
@ -1082,7 +1100,8 @@ mod test {
} }
// We create a new tree // We create a new tree
let input_buffer = Cursor::new(TEST_RESOURCES_FOLDER); let input_buffer =
Cursor::new(json!({ "resources_folder": TEST_RESOURCES_FOLDER }).to_string());
let mut rln = RLN::new(tree_height, input_buffer).unwrap(); let mut rln = RLN::new(tree_height, input_buffer).unwrap();
// We first add leaves one by one specifying the index // We first add leaves one by one specifying the index
@ -1177,7 +1196,8 @@ mod test {
let set_index = rng.gen_range(0..no_of_leaves) as usize; let set_index = rng.gen_range(0..no_of_leaves) as usize;
// We create a new tree // We create a new tree
let input_buffer = Cursor::new(TEST_RESOURCES_FOLDER); let input_buffer =
Cursor::new(json!({ "resources_folder": TEST_RESOURCES_FOLDER }).to_string());
let mut rln = RLN::new(tree_height, input_buffer).unwrap(); let mut rln = RLN::new(tree_height, input_buffer).unwrap();
// We add leaves in a batch into the tree // We add leaves in a batch into the tree
@ -1248,7 +1268,8 @@ mod test {
let bad_index = (1 << tree_height) - rng.gen_range(0..no_of_leaves) as usize; let bad_index = (1 << tree_height) - rng.gen_range(0..no_of_leaves) as usize;
// We create a new tree // We create a new tree
let input_buffer = Cursor::new(TEST_RESOURCES_FOLDER); let input_buffer =
Cursor::new(json!({ "resources_folder": TEST_RESOURCES_FOLDER }).to_string());
let mut rln = RLN::new(tree_height, input_buffer).unwrap(); let mut rln = RLN::new(tree_height, input_buffer).unwrap();
// Get root of empty tree // Get root of empty tree
@ -1277,7 +1298,8 @@ mod test {
fn test_groth16_proof() { fn test_groth16_proof() {
let tree_height = TEST_TREE_HEIGHT; let tree_height = TEST_TREE_HEIGHT;
let input_buffer = Cursor::new(TEST_RESOURCES_FOLDER); let input_buffer =
Cursor::new(json!({ "resources_folder": TEST_RESOURCES_FOLDER }).to_string());
let mut rln = RLN::new(tree_height, input_buffer).unwrap(); let mut rln = RLN::new(tree_height, input_buffer).unwrap();
// Note: we only test Groth16 proof generation, so we ignore setting the tree in the RLN object // Note: we only test Groth16 proof generation, so we ignore setting the tree in the RLN object
@ -1321,7 +1343,8 @@ mod test {
} }
// We create a new RLN instance // We create a new RLN instance
let input_buffer = Cursor::new(TEST_RESOURCES_FOLDER); let input_buffer =
Cursor::new(json!({ "resources_folder": TEST_RESOURCES_FOLDER }).to_string());
let mut rln = RLN::new(tree_height, input_buffer).unwrap(); let mut rln = RLN::new(tree_height, input_buffer).unwrap();
// We add leaves in a batch into the tree // We add leaves in a batch into the tree
@ -1385,7 +1408,8 @@ mod test {
} }
// We create a new RLN instance // We create a new RLN instance
let input_buffer = Cursor::new(TEST_RESOURCES_FOLDER); let input_buffer =
Cursor::new(json!({ "resources_folder": TEST_RESOURCES_FOLDER }).to_string());
let mut rln = RLN::new(tree_height, input_buffer).unwrap(); let mut rln = RLN::new(tree_height, input_buffer).unwrap();
// We add leaves in a batch into the tree // We add leaves in a batch into the tree
@ -1481,7 +1505,8 @@ mod test {
} }
// We create a new RLN instance // We create a new RLN instance
let input_buffer = Cursor::new(TEST_RESOURCES_FOLDER); let input_buffer =
Cursor::new(json!({ "resources_folder": TEST_RESOURCES_FOLDER }).to_string());
let mut rln = RLN::new(tree_height, input_buffer).unwrap(); let mut rln = RLN::new(tree_height, input_buffer).unwrap();
// We add leaves in a batch into the tree // We add leaves in a batch into the tree
@ -1567,7 +1592,8 @@ mod test {
let tree_height = TEST_TREE_HEIGHT; let tree_height = TEST_TREE_HEIGHT;
// We create a new RLN instance // We create a new RLN instance
let input_buffer = Cursor::new(TEST_RESOURCES_FOLDER); let input_buffer =
Cursor::new(json!({ "resources_folder": TEST_RESOURCES_FOLDER }).to_string());
let mut rln = RLN::new(tree_height, input_buffer).unwrap(); let mut rln = RLN::new(tree_height, input_buffer).unwrap();
// Generate identity pair // Generate identity pair

View File

@ -8,6 +8,7 @@ mod test {
use rln::protocol::*; use rln::protocol::*;
use rln::public::RLN; use rln::public::RLN;
use rln::utils::*; use rln::utils::*;
use serde_json::json;
use std::fs::File; use std::fs::File;
use std::io::Read; use std::io::Read;
use std::mem::MaybeUninit; use std::mem::MaybeUninit;
@ -28,7 +29,8 @@ mod test {
// We create a RLN instance // We create a RLN instance
let mut rln_pointer = MaybeUninit::<*mut RLN>::uninit(); let mut rln_pointer = MaybeUninit::<*mut RLN>::uninit();
let input_buffer = &Buffer::from(TEST_RESOURCES_FOLDER.as_bytes()); let input_config = json!({ "resource_folder": TEST_RESOURCES_FOLDER }).to_string();
let input_buffer = &Buffer::from(input_config.as_bytes());
let success = new(tree_height, input_buffer, rln_pointer.as_mut_ptr()); let success = new(tree_height, input_buffer, rln_pointer.as_mut_ptr());
assert!(success, "RLN object creation failed"); assert!(success, "RLN object creation failed");
let rln_pointer = unsafe { &mut *rln_pointer.assume_init() }; let rln_pointer = unsafe { &mut *rln_pointer.assume_init() };
@ -135,7 +137,8 @@ mod test {
// We create a RLN instance // We create a RLN instance
let mut rln_pointer = MaybeUninit::<*mut RLN>::uninit(); let mut rln_pointer = MaybeUninit::<*mut RLN>::uninit();
let input_buffer = &Buffer::from(TEST_RESOURCES_FOLDER.as_bytes()); let input_config = json!({ "resources_folder": TEST_RESOURCES_FOLDER }).to_string();
let input_buffer = &Buffer::from(input_config.as_bytes());
let success = new(tree_height, input_buffer, rln_pointer.as_mut_ptr()); let success = new(tree_height, input_buffer, rln_pointer.as_mut_ptr());
assert!(success, "RLN object creation failed"); assert!(success, "RLN object creation failed");
let rln_pointer = unsafe { &mut *rln_pointer.assume_init() }; let rln_pointer = unsafe { &mut *rln_pointer.assume_init() };
@ -232,7 +235,8 @@ mod test {
// We create a RLN instance // We create a RLN instance
let mut rln_pointer = MaybeUninit::<*mut RLN>::uninit(); let mut rln_pointer = MaybeUninit::<*mut RLN>::uninit();
let input_buffer = &Buffer::from(TEST_RESOURCES_FOLDER.as_bytes()); let input_config = json!({ "resources_folder": TEST_RESOURCES_FOLDER }).to_string();
let input_buffer = &Buffer::from(input_config.as_bytes());
let success = new(tree_height, input_buffer, rln_pointer.as_mut_ptr()); let success = new(tree_height, input_buffer, rln_pointer.as_mut_ptr());
assert!(success, "RLN object creation failed"); assert!(success, "RLN object creation failed");
let rln_pointer = unsafe { &mut *rln_pointer.assume_init() }; let rln_pointer = unsafe { &mut *rln_pointer.assume_init() };
@ -272,7 +276,8 @@ mod test {
// We create a RLN instance // We create a RLN instance
let mut rln_pointer = MaybeUninit::<*mut RLN>::uninit(); let mut rln_pointer = MaybeUninit::<*mut RLN>::uninit();
let input_buffer = &Buffer::from(TEST_RESOURCES_FOLDER.as_bytes()); let input_config = json!({ "resources_folder": TEST_RESOURCES_FOLDER }).to_string();
let input_buffer = &Buffer::from(input_config.as_bytes());
let success = new(tree_height, input_buffer, rln_pointer.as_mut_ptr()); let success = new(tree_height, input_buffer, rln_pointer.as_mut_ptr());
assert!(success, "RLN object creation failed"); assert!(success, "RLN object creation failed");
let rln_pointer = unsafe { &mut *rln_pointer.assume_init() }; let rln_pointer = unsafe { &mut *rln_pointer.assume_init() };
@ -440,7 +445,8 @@ mod test {
// We create a RLN instance // We create a RLN instance
let mut rln_pointer = MaybeUninit::<*mut RLN>::uninit(); let mut rln_pointer = MaybeUninit::<*mut RLN>::uninit();
let input_buffer = &Buffer::from(TEST_RESOURCES_FOLDER.as_bytes()); let input_config = json!({ "resources_folder": TEST_RESOURCES_FOLDER }).to_string();
let input_buffer = &Buffer::from(input_config.as_bytes());
let success = new(tree_height, input_buffer, rln_pointer.as_mut_ptr()); let success = new(tree_height, input_buffer, rln_pointer.as_mut_ptr());
assert!(success, "RLN object creation failed"); assert!(success, "RLN object creation failed");
let rln_pointer = unsafe { &mut *rln_pointer.assume_init() }; let rln_pointer = unsafe { &mut *rln_pointer.assume_init() };
@ -502,7 +508,8 @@ mod test {
// We create a RLN instance using a resource folder path // We create a RLN instance using a resource folder path
let mut rln_pointer = MaybeUninit::<*mut RLN>::uninit(); let mut rln_pointer = MaybeUninit::<*mut RLN>::uninit();
let input_buffer = &Buffer::from(TEST_RESOURCES_FOLDER.as_bytes()); let input_config = json!({ "resources_folder": TEST_RESOURCES_FOLDER }).to_string();
let input_buffer = &Buffer::from(input_config.as_bytes());
let success = new(tree_height, input_buffer, rln_pointer.as_mut_ptr()); let success = new(tree_height, input_buffer, rln_pointer.as_mut_ptr());
assert!(success, "RLN object creation failed"); assert!(success, "RLN object creation failed");
let rln_pointer = unsafe { &mut *rln_pointer.assume_init() }; let rln_pointer = unsafe { &mut *rln_pointer.assume_init() };
@ -582,7 +589,8 @@ mod test {
// We create a RLN instance // We create a RLN instance
let mut rln_pointer = MaybeUninit::<*mut RLN>::uninit(); let mut rln_pointer = MaybeUninit::<*mut RLN>::uninit();
let input_buffer = &Buffer::from(TEST_RESOURCES_FOLDER.as_bytes()); let input_config = json!({ "resources_folder": TEST_RESOURCES_FOLDER }).to_string();
let input_buffer = &Buffer::from(input_config.as_bytes());
let success = new(tree_height, input_buffer, rln_pointer.as_mut_ptr()); let success = new(tree_height, input_buffer, rln_pointer.as_mut_ptr());
assert!(success, "RLN object creation failed"); assert!(success, "RLN object creation failed");
let rln_pointer = unsafe { &mut *rln_pointer.assume_init() }; let rln_pointer = unsafe { &mut *rln_pointer.assume_init() };
@ -666,7 +674,8 @@ mod test {
// We create a RLN instance // We create a RLN instance
let mut rln_pointer = MaybeUninit::<*mut RLN>::uninit(); let mut rln_pointer = MaybeUninit::<*mut RLN>::uninit();
let input_buffer = &Buffer::from(TEST_RESOURCES_FOLDER.as_bytes()); let input_config = json!({ "resources_folder": TEST_RESOURCES_FOLDER }).to_string();
let input_buffer = &Buffer::from(input_config.as_bytes());
let success = new(tree_height, input_buffer, rln_pointer.as_mut_ptr()); let success = new(tree_height, input_buffer, rln_pointer.as_mut_ptr());
assert!(success, "RLN object creation failed"); assert!(success, "RLN object creation failed");
let rln_pointer = unsafe { &mut *rln_pointer.assume_init() }; let rln_pointer = unsafe { &mut *rln_pointer.assume_init() };
@ -784,7 +793,8 @@ mod test {
// We create a RLN instance // We create a RLN instance
let mut rln_pointer = MaybeUninit::<*mut RLN>::uninit(); let mut rln_pointer = MaybeUninit::<*mut RLN>::uninit();
let input_buffer = &Buffer::from(TEST_RESOURCES_FOLDER.as_bytes()); let input_config = json!({ "resources_folder": TEST_RESOURCES_FOLDER }).to_string();
let input_buffer = &Buffer::from(input_config.as_bytes());
let success = new(tree_height, input_buffer, rln_pointer.as_mut_ptr()); let success = new(tree_height, input_buffer, rln_pointer.as_mut_ptr());
assert!(success, "RLN object creation failed"); assert!(success, "RLN object creation failed");
let rln_pointer = unsafe { &mut *rln_pointer.assume_init() }; let rln_pointer = unsafe { &mut *rln_pointer.assume_init() };
@ -943,7 +953,8 @@ mod test {
// We create a RLN instance // We create a RLN instance
let mut rln_pointer = MaybeUninit::<*mut RLN>::uninit(); let mut rln_pointer = MaybeUninit::<*mut RLN>::uninit();
let input_buffer = &Buffer::from(TEST_RESOURCES_FOLDER.as_bytes()); let input_config = json!({ "resources_folder": TEST_RESOURCES_FOLDER }).to_string();
let input_buffer = &Buffer::from(input_config.as_bytes());
let success = new(tree_height, input_buffer, rln_pointer.as_mut_ptr()); let success = new(tree_height, input_buffer, rln_pointer.as_mut_ptr());
assert!(success, "RLN object creation failed"); assert!(success, "RLN object creation failed");
let rln_pointer = unsafe { &mut *rln_pointer.assume_init() }; let rln_pointer = unsafe { &mut *rln_pointer.assume_init() };
@ -982,7 +993,8 @@ mod test {
let tree_height = TEST_TREE_HEIGHT; let tree_height = TEST_TREE_HEIGHT;
// We create a RLN instance // We create a RLN instance
let mut rln_pointer = MaybeUninit::<*mut RLN>::uninit(); let mut rln_pointer = MaybeUninit::<*mut RLN>::uninit();
let input_buffer = &Buffer::from(TEST_RESOURCES_FOLDER.as_bytes()); let input_config = json!({ "resources_folder": TEST_RESOURCES_FOLDER }).to_string();
let input_buffer = &Buffer::from(input_config.as_bytes());
let success = new(tree_height, input_buffer, rln_pointer.as_mut_ptr()); let success = new(tree_height, input_buffer, rln_pointer.as_mut_ptr());
assert!(success, "RLN object creation failed"); assert!(success, "RLN object creation failed");
let rln_pointer = unsafe { &mut *rln_pointer.assume_init() }; let rln_pointer = unsafe { &mut *rln_pointer.assume_init() };

View File

@ -7,6 +7,7 @@ mod test {
use rln::protocol::{compute_tree_root, deserialize_identity_tuple}; use rln::protocol::{compute_tree_root, deserialize_identity_tuple};
use rln::public::{hash as public_hash, poseidon_hash as public_poseidon_hash, RLN}; use rln::public::{hash as public_hash, poseidon_hash as public_poseidon_hash, RLN};
use rln::utils::*; use rln::utils::*;
use serde_json::json;
use std::io::Cursor; use std::io::Cursor;
#[test] #[test]
@ -15,7 +16,8 @@ mod test {
let tree_height = TEST_TREE_HEIGHT; let tree_height = TEST_TREE_HEIGHT;
let leaf_index = 3; let leaf_index = 3;
let input_buffer = Cursor::new(TEST_RESOURCES_FOLDER); let input_buffer =
Cursor::new(json!({ "resources_folder": TEST_RESOURCES_FOLDER }).to_string());
let mut rln = RLN::new(tree_height, input_buffer).unwrap(); let mut rln = RLN::new(tree_height, input_buffer).unwrap();
// generate identity // generate identity

View File

@ -10,6 +10,7 @@ num-bigint = { version = "=0.4.3", default-features = false, features = ["rand"]
color-eyre = "=0.6.2" color-eyre = "=0.6.2"
pmtree = { git = "https://github.com/Rate-Limiting-Nullifier/pmtree", rev = "b3a02216cece3e9c24e1754ea381bf784fd1df48", optional = true} pmtree = { git = "https://github.com/Rate-Limiting-Nullifier/pmtree", rev = "b3a02216cece3e9c24e1754ea381bf784fd1df48", optional = true}
sled = "=0.34.7" sled = "=0.34.7"
serde = "1.0.44"
[dev-dependencies] [dev-dependencies]
ark-bn254 = "=0.4.0" ark-bn254 = "=0.4.0"

View File

@ -4,6 +4,7 @@ use std::{
cmp::max, cmp::max,
fmt::Debug, fmt::Debug,
iter::{once, repeat, successors}, iter::{once, repeat, successors},
str::FromStr,
}; };
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
@ -44,6 +45,17 @@ pub enum FullMerkleBranch<H: Hasher> {
#[derive(Clone, PartialEq, Eq)] #[derive(Clone, PartialEq, Eq)]
pub struct FullMerkleProof<H: Hasher>(pub Vec<FullMerkleBranch<H>>); pub struct FullMerkleProof<H: Hasher>(pub Vec<FullMerkleBranch<H>>);
#[derive(Default)]
pub struct FullMerkleConfig(());
impl FromStr for FullMerkleConfig {
type Err = Report;
fn from_str(_s: &str) -> Result<Self> {
Ok(FullMerkleConfig::default())
}
}
/// Implementations /// Implementations
impl<H: Hasher> ZerokitMerkleTree for FullMerkleTree<H> impl<H: Hasher> ZerokitMerkleTree for FullMerkleTree<H>
where where
@ -51,10 +63,10 @@ where
{ {
type Proof = FullMerkleProof<H>; type Proof = FullMerkleProof<H>;
type Hasher = H; type Hasher = H;
type Config = (); type Config = FullMerkleConfig;
fn default(depth: usize) -> Result<Self> { fn default(depth: usize) -> Result<Self> {
FullMerkleTree::<H>::new(depth, Self::Hasher::default_leaf(), ()) FullMerkleTree::<H>::new(depth, Self::Hasher::default_leaf(), Self::Config::default())
} }
/// Creates a new `MerkleTree` /// Creates a new `MerkleTree`

View File

@ -13,6 +13,8 @@
//! * Disk based storage backend (using mmaped files should be easy) //! * Disk based storage backend (using mmaped files should be easy)
//! * Implement serialization for tree and Merkle proof //! * Implement serialization for tree and Merkle proof
use std::str::FromStr;
use color_eyre::Result; use color_eyre::Result;
/// In the Hasher trait we define the node type, the default leaf /// In the Hasher trait we define the node type, the default leaf
@ -35,7 +37,7 @@ pub type FrOf<H> = <H as Hasher>::Fr;
pub trait ZerokitMerkleTree { pub trait ZerokitMerkleTree {
type Proof: ZerokitMerkleProof; type Proof: ZerokitMerkleProof;
type Hasher: Hasher; type Hasher: Hasher;
type Config: Default; type Config: Default + FromStr;
fn default(depth: usize) -> Result<Self> fn default(depth: usize) -> Result<Self>
where where

View File

@ -1,6 +1,7 @@
use crate::merkle_tree::{Hasher, ZerokitMerkleProof, ZerokitMerkleTree}; use crate::merkle_tree::{Hasher, ZerokitMerkleProof, ZerokitMerkleTree};
use color_eyre::{Report, Result}; use color_eyre::{Report, Result};
use std::collections::HashMap; use std::collections::HashMap;
use std::str::FromStr;
use std::{cmp::max, fmt::Debug}; use std::{cmp::max, fmt::Debug};
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
@ -35,6 +36,17 @@ where
#[derive(Clone, PartialEq, Eq)] #[derive(Clone, PartialEq, Eq)]
pub struct OptimalMerkleProof<H: Hasher>(pub Vec<(H::Fr, u8)>); pub struct OptimalMerkleProof<H: Hasher>(pub Vec<(H::Fr, u8)>);
#[derive(Default)]
pub struct OptimalMerkleConfig(());
impl FromStr for OptimalMerkleConfig {
type Err = Report;
fn from_str(_s: &str) -> Result<Self> {
Ok(OptimalMerkleConfig::default())
}
}
/// Implementations /// Implementations
impl<H: Hasher> ZerokitMerkleTree for OptimalMerkleTree<H> impl<H: Hasher> ZerokitMerkleTree for OptimalMerkleTree<H>
@ -43,10 +55,10 @@ where
{ {
type Proof = OptimalMerkleProof<H>; type Proof = OptimalMerkleProof<H>;
type Hasher = H; type Hasher = H;
type Config = (); type Config = OptimalMerkleConfig;
fn default(depth: usize) -> Result<Self> { fn default(depth: usize) -> Result<Self> {
OptimalMerkleTree::<H>::new(depth, H::default_leaf(), ()) OptimalMerkleTree::<H>::new(depth, H::default_leaf(), Self::Config::default())
} }
/// Creates a new `MerkleTree` /// Creates a new `MerkleTree`

View File

@ -3,7 +3,10 @@
mod test { mod test {
use hex_literal::hex; use hex_literal::hex;
use tiny_keccak::{Hasher as _, Keccak}; use tiny_keccak::{Hasher as _, Keccak};
use utils::{FullMerkleTree, Hasher, OptimalMerkleTree, ZerokitMerkleProof, ZerokitMerkleTree}; use utils::{
FullMerkleConfig, FullMerkleTree, Hasher, OptimalMerkleConfig, OptimalMerkleTree,
ZerokitMerkleProof, ZerokitMerkleTree,
};
#[derive(Clone, Copy, Eq, PartialEq)] #[derive(Clone, Copy, Eq, PartialEq)]
struct Keccak256; struct Keccak256;
@ -44,14 +47,17 @@ mod test {
hex!("a9bb8c3f1f12e9aa903a50c47f314b57610a3ab32f2d463293f58836def38d36"), hex!("a9bb8c3f1f12e9aa903a50c47f314b57610a3ab32f2d463293f58836def38d36"),
]; ];
let mut tree = FullMerkleTree::<Keccak256>::new(2, [0; 32], ()).unwrap(); let mut tree =
FullMerkleTree::<Keccak256>::new(2, [0; 32], FullMerkleConfig::default()).unwrap();
assert_eq!(tree.root(), default_tree_root); assert_eq!(tree.root(), default_tree_root);
for i in 0..leaves.len() { for i in 0..leaves.len() {
tree.set(i, leaves[i]).unwrap(); tree.set(i, leaves[i]).unwrap();
assert_eq!(tree.root(), roots[i]); assert_eq!(tree.root(), roots[i]);
} }
let mut tree = OptimalMerkleTree::<Keccak256>::new(2, [0; 32], ()).unwrap(); let mut tree =
OptimalMerkleTree::<Keccak256>::new(2, [0; 32], OptimalMerkleConfig::default())
.unwrap();
assert_eq!(tree.root(), default_tree_root); assert_eq!(tree.root(), default_tree_root);
for i in 0..leaves.len() { for i in 0..leaves.len() {
tree.set(i, leaves[i]).unwrap(); tree.set(i, leaves[i]).unwrap();
@ -69,7 +75,8 @@ mod test {
]; ];
// We thest the FullMerkleTree implementation // We thest the FullMerkleTree implementation
let mut tree = FullMerkleTree::<Keccak256>::new(2, [0; 32], ()).unwrap(); let mut tree =
FullMerkleTree::<Keccak256>::new(2, [0; 32], FullMerkleConfig::default()).unwrap();
for i in 0..leaves.len() { for i in 0..leaves.len() {
// We set the leaves // We set the leaves
tree.set(i, leaves[i]).unwrap(); tree.set(i, leaves[i]).unwrap();
@ -93,7 +100,9 @@ mod test {
} }
// We test the OptimalMerkleTree implementation // We test the OptimalMerkleTree implementation
let mut tree = OptimalMerkleTree::<Keccak256>::new(2, [0; 32], ()).unwrap(); let mut tree =
OptimalMerkleTree::<Keccak256>::new(2, [0; 32], OptimalMerkleConfig::default())
.unwrap();
for i in 0..leaves.len() { for i in 0..leaves.len() {
// We set the leaves // We set the leaves
tree.set(i, leaves[i]).unwrap(); tree.set(i, leaves[i]).unwrap();