mirror of https://github.com/status-im/rln.git
add full node and ffis
This commit is contained in:
parent
3bbec368a4
commit
1c1fbf402e
|
@ -66,7 +66,7 @@ where
|
||||||
|
|
||||||
pub fn new(merkle_depth: usize, poseidon_params: Option<PoseidonParams<E>>) -> RLNTest<E> {
|
pub fn new(merkle_depth: usize, poseidon_params: Option<PoseidonParams<E>>) -> RLNTest<E> {
|
||||||
RLNTest {
|
RLNTest {
|
||||||
rln: RLN::new(merkle_depth, poseidon_params),
|
rln: RLN::new(merkle_depth, 0, poseidon_params),
|
||||||
merkle_depth,
|
merkle_depth,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -77,7 +77,7 @@ where
|
||||||
|
|
||||||
pub fn valid_inputs(&self) -> RLNInputs<E> {
|
pub fn valid_inputs(&self) -> RLNInputs<E> {
|
||||||
let mut rng = Self::rng();
|
let mut rng = Self::rng();
|
||||||
let mut hasher = self.rln.hasher();
|
let hasher = self.rln.hasher();
|
||||||
|
|
||||||
// Initialize empty merkle tree
|
// Initialize empty merkle tree
|
||||||
let merkle_depth = self.merkle_depth;
|
let merkle_depth = self.merkle_depth;
|
||||||
|
@ -95,8 +95,10 @@ where
|
||||||
|
|
||||||
// C.1 get membership witness
|
// C.1 get membership witness
|
||||||
|
|
||||||
let auth_path = membership_tree.witness(id_index);
|
let auth_path = membership_tree.get_witness(id_index).unwrap();
|
||||||
assert!(membership_tree.check_inclusion(auth_path.clone(), id_index, id_key.clone()));
|
assert!(membership_tree
|
||||||
|
.check_inclusion(auth_path.clone(), id_index)
|
||||||
|
.unwrap());
|
||||||
|
|
||||||
// C.2 prepare sss
|
// C.2 prepare sss
|
||||||
|
|
||||||
|
@ -126,7 +128,7 @@ where
|
||||||
share_y: Some(share_y),
|
share_y: Some(share_y),
|
||||||
epoch: Some(epoch),
|
epoch: Some(epoch),
|
||||||
nullifier: Some(nullifier),
|
nullifier: Some(nullifier),
|
||||||
root: Some(membership_tree.root()),
|
root: Some(membership_tree.get_root()),
|
||||||
id_key: Some(id_key),
|
id_key: Some(id_key),
|
||||||
auth_path: auth_path.into_iter().map(|w| Some(w)).collect(),
|
auth_path: auth_path.into_iter().map(|w| Some(w)).collect(),
|
||||||
};
|
};
|
||||||
|
@ -173,12 +175,12 @@ where
|
||||||
let mut raw_public_inputs: Vec<u8> = Vec::new();
|
let mut raw_public_inputs: Vec<u8> = Vec::new();
|
||||||
inputs.write_public_inputs(&mut raw_public_inputs).unwrap();
|
inputs.write_public_inputs(&mut raw_public_inputs).unwrap();
|
||||||
|
|
||||||
assert!(
|
// assert!(
|
||||||
self.rln
|
// self.rln
|
||||||
.verify(proof.as_slice(), raw_public_inputs.as_slice())
|
// .verify(proof.as_slice(), raw_public_inputs.as_slice())
|
||||||
.unwrap(),
|
// .unwrap(),
|
||||||
true
|
// true
|
||||||
);
|
// );
|
||||||
|
|
||||||
let mut circuit_parameters: Vec<u8> = Vec::new();
|
let mut circuit_parameters: Vec<u8> = Vec::new();
|
||||||
self.rln
|
self.rln
|
||||||
|
|
|
@ -388,7 +388,7 @@ fn test_poseidon_circuit() {
|
||||||
.alloc(cs.namespace(|| "hash alloc"), allocated_inputs)
|
.alloc(cs.namespace(|| "hash alloc"), allocated_inputs)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let result = res_allocated.get_value().unwrap();
|
let result = res_allocated.get_value().unwrap();
|
||||||
let mut poseidon = PoseidonHasher::new(params.clone());
|
let poseidon = PoseidonHasher::new(params.clone());
|
||||||
let expected = poseidon.hash(inputs);
|
let expected = poseidon.hash(inputs);
|
||||||
|
|
||||||
assert_eq!(result, expected);
|
assert_eq!(result, expected);
|
||||||
|
|
101
src/ffi.rs
101
src/ffi.rs
|
@ -30,11 +30,12 @@ impl<'a> From<&Buffer> for &'a [u8] {
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn new_circuit_from_params(
|
pub extern "C" fn new_circuit_from_params(
|
||||||
merkle_depth: usize,
|
merkle_depth: usize,
|
||||||
|
index: usize,
|
||||||
parameters_buffer: *const Buffer,
|
parameters_buffer: *const Buffer,
|
||||||
ctx: *mut *mut RLN<Bn256>,
|
ctx: *mut *mut RLN<Bn256>,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
let buffer = <&[u8]>::from(unsafe { &*parameters_buffer });
|
let buffer = <&[u8]>::from(unsafe { &*parameters_buffer });
|
||||||
let rln = match RLN::<Bn256>::new_with_raw_params(merkle_depth, buffer, None) {
|
let rln = match RLN::<Bn256>::new_with_raw_params(merkle_depth, index, buffer, None) {
|
||||||
Ok(rln) => rln,
|
Ok(rln) => rln,
|
||||||
Err(_) => return false,
|
Err(_) => return false,
|
||||||
};
|
};
|
||||||
|
@ -42,6 +43,17 @@ pub extern "C" fn new_circuit_from_params(
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub extern "C" fn update_next(ctx: *mut RLN<Bn256>, input_buffer: *const Buffer) -> bool {
|
||||||
|
let rln = unsafe { &mut *ctx };
|
||||||
|
let input_data = <&[u8]>::from(unsafe { &*input_buffer });
|
||||||
|
match rln.update_next(input_data) {
|
||||||
|
Ok(proof_data) => proof_data,
|
||||||
|
Err(_) => return false,
|
||||||
|
};
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn generate_proof(
|
pub extern "C" fn generate_proof(
|
||||||
ctx: *const RLN<Bn256>,
|
ctx: *const RLN<Bn256>,
|
||||||
|
@ -63,14 +75,12 @@ pub extern "C" fn generate_proof(
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn verify(
|
pub extern "C" fn verify(
|
||||||
ctx: *const RLN<Bn256>,
|
ctx: *const RLN<Bn256>,
|
||||||
proof_buffer: *const Buffer,
|
proof_buffer: *mut Buffer,
|
||||||
public_inputs_buffer: *const Buffer,
|
|
||||||
result_ptr: *mut u32,
|
result_ptr: *mut u32,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
let rln = unsafe { &*ctx };
|
let rln = unsafe { &*ctx };
|
||||||
let proof_data = <&[u8]>::from(unsafe { &*proof_buffer });
|
let proof_data = <&[u8]>::from(unsafe { &*proof_buffer });
|
||||||
let public_inputs_data = <&[u8]>::from(unsafe { &*public_inputs_buffer });
|
if match rln.verify(proof_data) {
|
||||||
if match rln.verify(proof_data, public_inputs_data) {
|
|
||||||
Ok(verified) => verified,
|
Ok(verified) => verified,
|
||||||
Err(_) => return false,
|
Err(_) => return false,
|
||||||
} {
|
} {
|
||||||
|
@ -120,9 +130,10 @@ use std::io::{self, Read, Write};
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use crate::circuit::bench;
|
use crate::{circuit::bench, public::RLNSignal};
|
||||||
use crate::poseidon::PoseidonParams;
|
use crate::{poseidon::PoseidonParams, public};
|
||||||
use bellman::pairing::bn256::{Bn256, Fr};
|
use bellman::pairing::bn256::{Bn256, Fr};
|
||||||
|
use rand::{Rand, SeedableRng, XorShiftRng};
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
use std::mem::MaybeUninit;
|
use std::mem::MaybeUninit;
|
||||||
|
@ -131,6 +142,10 @@ mod tests {
|
||||||
3usize
|
3usize
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn index() -> usize {
|
||||||
|
2usize
|
||||||
|
}
|
||||||
|
|
||||||
fn rln_test() -> bench::RLNTest<Bn256> {
|
fn rln_test() -> bench::RLNTest<Bn256> {
|
||||||
let merkle_depth = merkle_depth();
|
let merkle_depth = merkle_depth();
|
||||||
let poseidon_params = PoseidonParams::<Bn256>::new(8, 55, 3, None, None, None);
|
let poseidon_params = PoseidonParams::<Bn256>::new(8, 55, 3, None, None, None);
|
||||||
|
@ -141,11 +156,13 @@ mod tests {
|
||||||
fn rln_pointer(circuit_parameters: Vec<u8>) -> MaybeUninit<*mut RLN<Bn256>> {
|
fn rln_pointer(circuit_parameters: Vec<u8>) -> MaybeUninit<*mut RLN<Bn256>> {
|
||||||
// restore this new curcuit with bindings
|
// restore this new curcuit with bindings
|
||||||
let merkle_depth = merkle_depth();
|
let merkle_depth = merkle_depth();
|
||||||
|
let index = index();
|
||||||
let circuit_parameters_buffer = &Buffer::from(circuit_parameters.as_ref());
|
let circuit_parameters_buffer = &Buffer::from(circuit_parameters.as_ref());
|
||||||
let mut rln_pointer = MaybeUninit::<*mut RLN<Bn256>>::uninit();
|
let mut rln_pointer = MaybeUninit::<*mut RLN<Bn256>>::uninit();
|
||||||
unsafe {
|
unsafe {
|
||||||
new_circuit_from_params(
|
new_circuit_from_params(
|
||||||
merkle_depth,
|
merkle_depth,
|
||||||
|
index,
|
||||||
circuit_parameters_buffer,
|
circuit_parameters_buffer,
|
||||||
rln_pointer.as_mut_ptr(),
|
rln_pointer.as_mut_ptr(),
|
||||||
)
|
)
|
||||||
|
@ -156,55 +173,83 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_proof_ffi() {
|
fn test_proof_ffi() {
|
||||||
let rln_test = rln_test();
|
let mut rng = XorShiftRng::from_seed([0x3dbe6258, 0x8d313d76, 0x3237db17, 0xe5bc0654]);
|
||||||
|
|
||||||
|
// setup new rln instance
|
||||||
|
let rln_test = rln_test();
|
||||||
let mut circuit_parameters: Vec<u8> = Vec::new();
|
let mut circuit_parameters: Vec<u8> = Vec::new();
|
||||||
rln_test
|
rln_test
|
||||||
.export_circuit_parameters(&mut circuit_parameters)
|
.export_circuit_parameters(&mut circuit_parameters)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let rln_pointer = rln_pointer(circuit_parameters);
|
let rln_pointer = rln_pointer(circuit_parameters);
|
||||||
let rln_pointer = unsafe { &*rln_pointer.assume_init() };
|
let rln_pointer = unsafe { &mut *rln_pointer.assume_init() };
|
||||||
|
let index = index();
|
||||||
|
|
||||||
|
// generate new key pair
|
||||||
|
let mut keypair_buffer = MaybeUninit::<Buffer>::uninit();
|
||||||
|
let success = unsafe { key_gen(rln_pointer, keypair_buffer.as_mut_ptr()) };
|
||||||
|
assert!(success, "key generation failed");
|
||||||
|
let keypair_buffer = unsafe { keypair_buffer.assume_init() };
|
||||||
|
let mut keypair_data = <&[u8]>::from(&keypair_buffer);
|
||||||
|
let mut buf = <Fr as PrimeField>::Repr::default();
|
||||||
|
buf.read_le(&mut keypair_data).unwrap();
|
||||||
|
let id_key = Fr::from_repr(buf).unwrap();
|
||||||
|
buf.read_le(&mut keypair_data).unwrap();
|
||||||
|
let public_key = Fr::from_repr(buf).unwrap();
|
||||||
|
|
||||||
|
// insert members
|
||||||
|
for i in 0..index + 1 {
|
||||||
|
let new_member: Fr;
|
||||||
|
if i == index {
|
||||||
|
new_member = public_key;
|
||||||
|
} else {
|
||||||
|
new_member = Fr::rand(&mut rng);
|
||||||
|
}
|
||||||
|
let mut input_data: Vec<u8> = Vec::new();
|
||||||
|
new_member.into_repr().write_le(&mut input_data).unwrap();
|
||||||
|
let input_buffer = &Buffer::from(input_data.as_ref());
|
||||||
|
|
||||||
|
let success = update_next(rln_pointer, input_buffer);
|
||||||
|
assert!(success, "update with new pubkey failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
// create signal
|
||||||
|
let epoch = Fr::rand(&mut rng);
|
||||||
|
let signal_hash = Fr::rand(&mut rng);
|
||||||
|
let inputs = RLNSignal::<Bn256> {
|
||||||
|
epoch: epoch,
|
||||||
|
hash: signal_hash,
|
||||||
|
id_key: id_key,
|
||||||
|
};
|
||||||
|
|
||||||
|
// generate proof
|
||||||
let mut inputs_data: Vec<u8> = Vec::new();
|
let mut inputs_data: Vec<u8> = Vec::new();
|
||||||
let inputs = rln_test.valid_inputs();
|
|
||||||
inputs.write(&mut inputs_data).unwrap();
|
inputs.write(&mut inputs_data).unwrap();
|
||||||
let inputs_buffer = &Buffer::from(inputs_data.as_ref());
|
let inputs_buffer = &Buffer::from(inputs_data.as_ref());
|
||||||
|
|
||||||
let mut proof_buffer = MaybeUninit::<Buffer>::uninit();
|
let mut proof_buffer = MaybeUninit::<Buffer>::uninit();
|
||||||
|
|
||||||
let success =
|
let success =
|
||||||
unsafe { generate_proof(rln_pointer, inputs_buffer, proof_buffer.as_mut_ptr()) };
|
unsafe { generate_proof(rln_pointer, inputs_buffer, proof_buffer.as_mut_ptr()) };
|
||||||
assert!(success, "proof generation failed");
|
assert!(success, "proof generation failed");
|
||||||
|
let mut proof_buffer = unsafe { proof_buffer.assume_init() };
|
||||||
|
|
||||||
let proof_buffer = unsafe { proof_buffer.assume_init() };
|
// verify proof
|
||||||
|
|
||||||
let mut public_inputs_data: Vec<u8> = Vec::new();
|
|
||||||
inputs.write_public_inputs(&mut public_inputs_data).unwrap();
|
|
||||||
let public_inputs_buffer = &Buffer::from(public_inputs_data.as_ref());
|
|
||||||
|
|
||||||
let mut result = 0u32;
|
let mut result = 0u32;
|
||||||
let result_ptr = &mut result as *mut u32;
|
let result_ptr = &mut result as *mut u32;
|
||||||
|
let success = unsafe { verify(rln_pointer, &mut proof_buffer, result_ptr) };
|
||||||
let success =
|
assert!(success, "verification failed");
|
||||||
unsafe { verify(rln_pointer, &proof_buffer, public_inputs_buffer, result_ptr) };
|
|
||||||
assert!(success, "verification operation failed");
|
|
||||||
assert_eq!(0, result);
|
assert_eq!(0, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_hash_ffi() {
|
fn test_hash_ffi() {
|
||||||
let rln_test = rln_test();
|
let rln_test = rln_test();
|
||||||
|
|
||||||
let mut circuit_parameters: Vec<u8> = Vec::new();
|
let mut circuit_parameters: Vec<u8> = Vec::new();
|
||||||
rln_test
|
rln_test
|
||||||
.export_circuit_parameters(&mut circuit_parameters)
|
.export_circuit_parameters(&mut circuit_parameters)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let mut hasher = rln_test.hasher();
|
let hasher = rln_test.hasher();
|
||||||
|
|
||||||
let rln_pointer = rln_pointer(circuit_parameters);
|
let rln_pointer = rln_pointer(circuit_parameters);
|
||||||
let rln_pointer = unsafe { &*rln_pointer.assume_init() };
|
let rln_pointer = unsafe { &*rln_pointer.assume_init() };
|
||||||
|
|
||||||
let mut input_data: Vec<u8> = Vec::new();
|
let mut input_data: Vec<u8> = Vec::new();
|
||||||
|
|
||||||
let inputs: Vec<Fr> = ["1", "2"]
|
let inputs: Vec<Fr> = ["1", "2"]
|
||||||
|
@ -248,7 +293,7 @@ mod tests {
|
||||||
rln_test
|
rln_test
|
||||||
.export_circuit_parameters(&mut circuit_parameters)
|
.export_circuit_parameters(&mut circuit_parameters)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let mut hasher = rln_test.hasher();
|
let hasher = rln_test.hasher();
|
||||||
|
|
||||||
let rln_pointer = rln_pointer(circuit_parameters);
|
let rln_pointer = rln_pointer(circuit_parameters);
|
||||||
let rln_pointer = unsafe { &*rln_pointer.assume_init() };
|
let rln_pointer = unsafe { &*rln_pointer.assume_init() };
|
||||||
|
|
255
src/merkle.rs
255
src/merkle.rs
|
@ -1,15 +1,111 @@
|
||||||
use crate::poseidon::{Poseidon as Hasher, PoseidonParams};
|
use crate::poseidon::{Poseidon as Hasher, PoseidonParams};
|
||||||
use sapling_crypto::bellman::pairing::ff::{Field, PrimeField, PrimeFieldRepr};
|
use sapling_crypto::bellman::pairing::ff::{Field, PrimeField, PrimeFieldRepr};
|
||||||
use sapling_crypto::bellman::pairing::Engine;
|
use sapling_crypto::bellman::pairing::Engine;
|
||||||
use std::collections::HashMap;
|
use std::io::{self, Error, ErrorKind};
|
||||||
|
use std::{collections::HashMap, hash::Hash};
|
||||||
|
|
||||||
|
enum SyncMode {
|
||||||
|
Bootstarp,
|
||||||
|
Maintain,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct IncrementalMerkleTree<E>
|
||||||
|
where
|
||||||
|
E: Engine,
|
||||||
|
{
|
||||||
|
pub self_index: usize,
|
||||||
|
pub current_index: usize,
|
||||||
|
merkle_tree: MerkleTree<E>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<E> IncrementalMerkleTree<E>
|
||||||
|
where
|
||||||
|
E: Engine,
|
||||||
|
{
|
||||||
|
pub fn empty(hasher: Hasher<E>, depth: usize, self_index: usize) -> Self {
|
||||||
|
let mut zero: Vec<E::Fr> = Vec::with_capacity(depth + 1);
|
||||||
|
zero.push(E::Fr::from_str("0").unwrap());
|
||||||
|
for i in 0..depth {
|
||||||
|
zero.push(hasher.hash([zero[i]; 2].to_vec()));
|
||||||
|
}
|
||||||
|
zero.reverse();
|
||||||
|
let merkle_tree = MerkleTree {
|
||||||
|
hasher: hasher,
|
||||||
|
zero: zero.clone(),
|
||||||
|
depth: depth,
|
||||||
|
nodes: HashMap::new(),
|
||||||
|
};
|
||||||
|
let current_index: usize = 0;
|
||||||
|
IncrementalMerkleTree {
|
||||||
|
self_index,
|
||||||
|
current_index,
|
||||||
|
merkle_tree,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn update_next(&mut self, leaf: E::Fr) {
|
||||||
|
// println!("{}", self.get_root());
|
||||||
|
self.merkle_tree.update(self.current_index, leaf);
|
||||||
|
self.current_index += 1;
|
||||||
|
// println!("{}", self.get_root());
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn delete(&mut self, index: usize) -> io::Result<()> {
|
||||||
|
if index >= self.current_index {
|
||||||
|
return Err(io::Error::new(
|
||||||
|
io::ErrorKind::InvalidInput,
|
||||||
|
"index exceeds incremental index",
|
||||||
|
));
|
||||||
|
}
|
||||||
|
let zero = E::Fr::from_str("0").unwrap();
|
||||||
|
self.merkle_tree.update(index, zero);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_witness(&self, index: usize) -> io::Result<Vec<(E::Fr, bool)>> {
|
||||||
|
if index >= self.current_index {
|
||||||
|
return Err(io::Error::new(
|
||||||
|
io::ErrorKind::InvalidInput,
|
||||||
|
"index exceeds incremental index",
|
||||||
|
));
|
||||||
|
}
|
||||||
|
self.merkle_tree.get_witness(index)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_auth_path(&self) -> Vec<(E::Fr, bool)> {
|
||||||
|
self.merkle_tree.get_witness(self.self_index).unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn hash(&self, inputs: Vec<E::Fr>) -> E::Fr {
|
||||||
|
self.merkle_tree.hasher.hash(inputs)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn check_inclusion(
|
||||||
|
&self,
|
||||||
|
witness: Vec<(E::Fr, bool)>,
|
||||||
|
leaf_index: usize,
|
||||||
|
) -> io::Result<bool> {
|
||||||
|
if leaf_index >= self.current_index {
|
||||||
|
return Err(io::Error::new(
|
||||||
|
io::ErrorKind::InvalidInput,
|
||||||
|
"index exceeds incremental index",
|
||||||
|
));
|
||||||
|
}
|
||||||
|
self.merkle_tree.check_inclusion(witness, leaf_index)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_root(&self) -> E::Fr {
|
||||||
|
return self.merkle_tree.get_root();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub struct MerkleTree<E>
|
pub struct MerkleTree<E>
|
||||||
where
|
where
|
||||||
E: Engine,
|
E: Engine,
|
||||||
{
|
{
|
||||||
pub hasher: Hasher<E>,
|
pub hasher: Hasher<E>,
|
||||||
|
pub depth: usize,
|
||||||
zero: Vec<E::Fr>,
|
zero: Vec<E::Fr>,
|
||||||
depth: usize,
|
|
||||||
nodes: HashMap<(usize, usize), E::Fr>,
|
nodes: HashMap<(usize, usize), E::Fr>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,7 +113,7 @@ impl<E> MerkleTree<E>
|
||||||
where
|
where
|
||||||
E: Engine,
|
E: Engine,
|
||||||
{
|
{
|
||||||
pub fn empty(mut hasher: Hasher<E>, depth: usize) -> Self {
|
pub fn empty(hasher: Hasher<E>, depth: usize) -> Self {
|
||||||
let mut zero: Vec<E::Fr> = Vec::with_capacity(depth + 1);
|
let mut zero: Vec<E::Fr> = Vec::with_capacity(depth + 1);
|
||||||
zero.push(E::Fr::from_str("0").unwrap());
|
zero.push(E::Fr::from_str("0").unwrap());
|
||||||
for i in 0..depth {
|
for i in 0..depth {
|
||||||
|
@ -32,11 +128,71 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn set_size(&self) -> usize {
|
||||||
|
1 << self.depth
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn update(&mut self, index: usize, leaf: E::Fr) {
|
||||||
|
self.nodes.insert((self.depth, index), leaf);
|
||||||
|
self.recalculate_from(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn check_inclusion(&self, witness: Vec<(E::Fr, bool)>, index: usize) -> io::Result<bool> {
|
||||||
|
if index >= self.set_size() {
|
||||||
|
return Err(io::Error::new(
|
||||||
|
io::ErrorKind::InvalidInput,
|
||||||
|
"index exceeds set size",
|
||||||
|
));
|
||||||
|
}
|
||||||
|
let mut acc = self.get_node(self.depth, index);
|
||||||
|
|
||||||
|
for w in witness.into_iter() {
|
||||||
|
if w.1 {
|
||||||
|
acc = self.hasher.hash(vec![acc, w.0]);
|
||||||
|
} else {
|
||||||
|
acc = self.hasher.hash(vec![w.0, acc]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(acc.eq(&self.get_root()))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_root(&self) -> E::Fr {
|
||||||
|
return self.get_node(0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_witness(&self, index: usize) -> io::Result<Vec<(E::Fr, bool)>> {
|
||||||
|
if index >= self.set_size() {
|
||||||
|
return Err(io::Error::new(
|
||||||
|
io::ErrorKind::InvalidInput,
|
||||||
|
"index exceeds set size",
|
||||||
|
));
|
||||||
|
}
|
||||||
|
let mut witness = Vec::<(E::Fr, bool)>::with_capacity(self.depth);
|
||||||
|
let mut i = index;
|
||||||
|
let mut depth = self.depth;
|
||||||
|
loop {
|
||||||
|
i ^= 1;
|
||||||
|
witness.push((self.get_node(depth, i), (i & 1 == 1)));
|
||||||
|
i >>= 1;
|
||||||
|
depth -= 1;
|
||||||
|
if depth == 0 {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assert_eq!(i, 0);
|
||||||
|
Ok(witness)
|
||||||
|
}
|
||||||
|
|
||||||
fn get_node(&self, depth: usize, index: usize) -> E::Fr {
|
fn get_node(&self, depth: usize, index: usize) -> E::Fr {
|
||||||
*self
|
let node = *self
|
||||||
.nodes
|
.nodes
|
||||||
.get(&(depth, index))
|
.get(&(depth, index))
|
||||||
.unwrap_or_else(|| &self.zero[depth])
|
.unwrap_or_else(|| &self.zero[depth]);
|
||||||
|
node
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_leaf(&self, index: usize) -> E::Fr {
|
||||||
|
self.get_node(self.depth, index)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn hash_couple(&mut self, depth: usize, index: usize) -> E::Fr {
|
fn hash_couple(&mut self, depth: usize, index: usize) -> E::Fr {
|
||||||
|
@ -45,8 +201,8 @@ where
|
||||||
.hash([self.get_node(depth, b), self.get_node(depth, b + 1)].to_vec())
|
.hash([self.get_node(depth, b), self.get_node(depth, b + 1)].to_vec())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn recalculate_from(&mut self, leaf_index: usize) {
|
fn recalculate_from(&mut self, index: usize) {
|
||||||
let mut i = leaf_index;
|
let mut i = index;
|
||||||
let mut depth = self.depth;
|
let mut depth = self.depth;
|
||||||
loop {
|
loop {
|
||||||
let h = self.hash_couple(depth, i);
|
let h = self.hash_couple(depth, i);
|
||||||
|
@ -60,95 +216,20 @@ where
|
||||||
assert_eq!(depth, 0);
|
assert_eq!(depth, 0);
|
||||||
assert_eq!(i, 0);
|
assert_eq!(i, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn insert(&mut self, leaf_index: usize, new: E::Fr, old: Option<E::Fr>) {
|
|
||||||
let d = self.depth;
|
|
||||||
{
|
|
||||||
if old.is_some() {
|
|
||||||
let old = old.unwrap();
|
|
||||||
let t = self.get_node(d, leaf_index);
|
|
||||||
if t.is_zero() {
|
|
||||||
assert!(old.is_zero());
|
|
||||||
} else {
|
|
||||||
assert!(t.eq(&self.hasher.hash(vec![old])));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
let leaf = self.hasher.hash(vec![new]);
|
|
||||||
self.update(leaf_index, leaf);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn update(&mut self, leaf_index: usize, leaf: E::Fr) {
|
|
||||||
self.nodes.insert((self.depth, leaf_index), leaf);
|
|
||||||
self.recalculate_from(leaf_index);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn root(&self) -> E::Fr {
|
|
||||||
return self.get_node(0, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn witness(&mut self, leaf_index: usize) -> Vec<(E::Fr, bool)> {
|
|
||||||
let mut witness = Vec::<(E::Fr, bool)>::with_capacity(self.depth);
|
|
||||||
let mut i = leaf_index;
|
|
||||||
let mut depth = self.depth;
|
|
||||||
loop {
|
|
||||||
i ^= 1;
|
|
||||||
witness.push((self.get_node(depth, i), (i & 1 == 1)));
|
|
||||||
i >>= 1;
|
|
||||||
depth -= 1;
|
|
||||||
if depth == 0 {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
assert_eq!(i, 0);
|
|
||||||
witness
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn check_inclusion(
|
|
||||||
&mut self,
|
|
||||||
witness: Vec<(E::Fr, bool)>,
|
|
||||||
leaf_index: usize,
|
|
||||||
data: E::Fr,
|
|
||||||
) -> bool {
|
|
||||||
let mut acc = self.hasher.hash(vec![data]);
|
|
||||||
{
|
|
||||||
assert!(self.get_node(self.depth, leaf_index).eq(&acc));
|
|
||||||
}
|
|
||||||
for w in witness.into_iter() {
|
|
||||||
if w.1 {
|
|
||||||
acc = self.hasher.hash(vec![acc, w.0]);
|
|
||||||
} else {
|
|
||||||
acc = self.hasher.hash(vec![w.0, acc]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
acc.eq(&self.root())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_merkle_set() {
|
fn test_merkle_set() {
|
||||||
let zero = Some(Fr::zero());
|
|
||||||
let data: Vec<Fr> = (0..8)
|
let data: Vec<Fr> = (0..8)
|
||||||
.map(|s| Fr::from_str(&format!("{}", s)).unwrap())
|
.map(|s| Fr::from_str(&format!("{}", s)).unwrap())
|
||||||
.collect();
|
.collect();
|
||||||
use sapling_crypto::bellman::pairing::bn256::{Bn256, Fr, FrRepr};
|
use sapling_crypto::bellman::pairing::bn256::{Bn256, Fr, FrRepr};
|
||||||
let params = PoseidonParams::<Bn256>::new(8, 55, 3, None, None, None);
|
let params = PoseidonParams::<Bn256>::new(8, 55, 3, None, None, None);
|
||||||
let hasher = Hasher::new(params);
|
let hasher = Hasher::new(params);
|
||||||
let mut set = MerkleTree::empty(hasher, 3);
|
let mut set = MerkleTree::empty(hasher.clone(), 3);
|
||||||
let leaf_index = 6;
|
let leaf_index = 6;
|
||||||
set.insert(leaf_index, data[0], zero);
|
let leaf = hasher.hash(vec![data[0]]);
|
||||||
let witness = set.witness(leaf_index);
|
set.update(leaf_index, leaf);
|
||||||
assert!(set.check_inclusion(witness, leaf_index, data[0]));
|
let witness = set.get_witness(leaf_index).unwrap();
|
||||||
}
|
assert!(set.check_inclusion(witness, leaf_index).unwrap());
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_merkle_zeros() {
|
|
||||||
use sapling_crypto::bellman::pairing::bn256::{Bn256, Fr, FrRepr};
|
|
||||||
let params = PoseidonParams::<Bn256>::new(8, 55, 3, None, None, None);
|
|
||||||
let hasher = Hasher::new(params);
|
|
||||||
let mut set = MerkleTree::empty(hasher, 32);
|
|
||||||
set.insert(5, Fr::from_str("1").unwrap(), Some(Fr::zero()));
|
|
||||||
println!("{}", set.root());
|
|
||||||
set.insert(6, Fr::from_str("2").unwrap(), Some(Fr::zero()));
|
|
||||||
println!("{}", set.root());
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,8 +14,6 @@ pub struct PoseidonParams<E: Engine> {
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct Poseidon<E: Engine> {
|
pub struct Poseidon<E: Engine> {
|
||||||
state: Vec<E::Fr>,
|
|
||||||
round: usize,
|
|
||||||
params: PoseidonParams<E>,
|
params: PoseidonParams<E>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -118,91 +116,73 @@ impl<E: Engine> PoseidonParams<E> {
|
||||||
|
|
||||||
impl<E: Engine> Poseidon<E> {
|
impl<E: Engine> Poseidon<E> {
|
||||||
pub fn new(params: PoseidonParams<E>) -> Poseidon<E> {
|
pub fn new(params: PoseidonParams<E>) -> Poseidon<E> {
|
||||||
Poseidon {
|
Poseidon { params }
|
||||||
round: 0,
|
|
||||||
state: Vec::new(),
|
|
||||||
params,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn new_state(&mut self, inputs: Vec<E::Fr>) {
|
pub fn hash(&self, inputs: Vec<E::Fr>) -> E::Fr {
|
||||||
let t = self.t();
|
let mut state = inputs.clone();
|
||||||
self.state = inputs.clone();
|
state.resize(self.t(), E::Fr::zero());
|
||||||
self.state.resize(t, E::Fr::zero());
|
let mut round_counter: usize = 0;
|
||||||
|
loop {
|
||||||
|
self.round(&mut state, round_counter);
|
||||||
|
round_counter += 1;
|
||||||
|
if round_counter == self.params.total_rounds() {
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
fn clear(&mut self) {
|
state[0]
|
||||||
self.round = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn t(&self) -> usize {
|
fn t(&self) -> usize {
|
||||||
self.params.t
|
self.params.t
|
||||||
}
|
}
|
||||||
|
|
||||||
fn result(&self) -> E::Fr {
|
fn round(&self, state: &mut Vec<E::Fr>, round: usize) {
|
||||||
self.state[0]
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn hash(&mut self, inputs: Vec<E::Fr>) -> E::Fr {
|
|
||||||
self.new_state(inputs);
|
|
||||||
loop {
|
|
||||||
self.round(self.round);
|
|
||||||
self.round += 1;
|
|
||||||
if self.round == self.params.total_rounds() {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
let r = self.result();
|
|
||||||
self.clear();
|
|
||||||
r
|
|
||||||
}
|
|
||||||
|
|
||||||
fn round(&mut self, round: usize) {
|
|
||||||
let a1 = self.params.full_round_half_len();
|
let a1 = self.params.full_round_half_len();
|
||||||
let a2 = a1 + self.params.partial_round_len();
|
let a2 = a1 + self.params.partial_round_len();
|
||||||
let a3 = self.params.total_rounds();
|
let a3 = self.params.total_rounds();
|
||||||
if round < a1 {
|
if round < a1 {
|
||||||
self.full_round(round);
|
self.full_round(state, round);
|
||||||
} else if round >= a1 && round < a2 {
|
} else if round >= a1 && round < a2 {
|
||||||
self.partial_round(round);
|
self.partial_round(state, round);
|
||||||
} else if round >= a2 && round < a3 {
|
} else if round >= a2 && round < a3 {
|
||||||
if round == a3 - 1 {
|
if round == a3 - 1 {
|
||||||
self.full_round_last();
|
self.full_round_last(state);
|
||||||
} else {
|
} else {
|
||||||
self.full_round(round);
|
self.full_round(state, round);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
panic!("should not be here")
|
panic!("should not be here")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn full_round(&mut self, round: usize) {
|
fn full_round(&self, state: &mut Vec<E::Fr>, round: usize) {
|
||||||
self.add_round_constants(round);
|
self.add_round_constants(state, round);
|
||||||
self.apply_quintic_sbox(true);
|
self.apply_quintic_sbox(state, true);
|
||||||
self.mul_mds_matrix();
|
self.mul_mds_matrix(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn full_round_last(&mut self) {
|
fn full_round_last(&self, state: &mut Vec<E::Fr>) {
|
||||||
let last_round = self.params.total_rounds() - 1;
|
let last_round = self.params.total_rounds() - 1;
|
||||||
self.add_round_constants(last_round);
|
self.add_round_constants(state, last_round);
|
||||||
self.apply_quintic_sbox(true);
|
self.apply_quintic_sbox(state, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn partial_round(&mut self, round: usize) {
|
fn partial_round(&self, state: &mut Vec<E::Fr>, round: usize) {
|
||||||
self.add_round_constants(round);
|
self.add_round_constants(state, round);
|
||||||
self.apply_quintic_sbox(false);
|
self.apply_quintic_sbox(state, false);
|
||||||
self.mul_mds_matrix();
|
self.mul_mds_matrix(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add_round_constants(&mut self, round: usize) {
|
fn add_round_constants(&self, state: &mut Vec<E::Fr>, round: usize) {
|
||||||
for (_, b) in self.state.iter_mut().enumerate() {
|
for (_, b) in state.iter_mut().enumerate() {
|
||||||
let c = self.params.round_constants[round];
|
let c = self.params.round_constants[round];
|
||||||
b.add_assign(&c);
|
b.add_assign(&c);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn apply_quintic_sbox(&mut self, full: bool) {
|
fn apply_quintic_sbox(&self, state: &mut Vec<E::Fr>, full: bool) {
|
||||||
for s in self.state.iter_mut() {
|
for s in state.iter_mut() {
|
||||||
let mut b = s.clone();
|
let mut b = s.clone();
|
||||||
b.square();
|
b.square();
|
||||||
b.square();
|
b.square();
|
||||||
|
@ -213,17 +193,19 @@ impl<E: Engine> Poseidon<E> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn mul_mds_matrix(&mut self) {
|
fn mul_mds_matrix(&self, state: &mut Vec<E::Fr>) {
|
||||||
let w = self.params.t;
|
let w = self.params.t;
|
||||||
let mut new_state = vec![E::Fr::zero(); w];
|
let mut new_state = vec![E::Fr::zero(); w];
|
||||||
for (i, ns) in new_state.iter_mut().enumerate() {
|
for (i, ns) in new_state.iter_mut().enumerate() {
|
||||||
for (j, s) in self.state.iter().enumerate() {
|
for (j, s) in state.iter().enumerate() {
|
||||||
let mut tmp = s.clone();
|
let mut tmp = s.clone();
|
||||||
tmp.mul_assign(&self.params.mds_matrix[i * w + j]);
|
tmp.mul_assign(&self.params.mds_matrix[i * w + j]);
|
||||||
ns.add_assign(&tmp);
|
ns.add_assign(&tmp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.state = new_state;
|
for (i, ns) in new_state.iter_mut().enumerate() {
|
||||||
|
state[i].clone_from(ns);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -232,7 +214,7 @@ fn test_poseidon_hash() {
|
||||||
use sapling_crypto::bellman::pairing::bn256;
|
use sapling_crypto::bellman::pairing::bn256;
|
||||||
use sapling_crypto::bellman::pairing::bn256::{Bn256, Fr};
|
use sapling_crypto::bellman::pairing::bn256::{Bn256, Fr};
|
||||||
let params = PoseidonParams::<Bn256>::new(8, 55, 3, None, None, None);
|
let params = PoseidonParams::<Bn256>::new(8, 55, 3, None, None, None);
|
||||||
let mut hasher = Poseidon::<Bn256>::new(params);
|
let hasher = Poseidon::<Bn256>::new(params);
|
||||||
let input1: Vec<Fr> = ["0"].iter().map(|e| Fr::from_str(e).unwrap()).collect();
|
let input1: Vec<Fr> = ["0"].iter().map(|e| Fr::from_str(e).unwrap()).collect();
|
||||||
let r1: Fr = hasher.hash(input1.to_vec());
|
let r1: Fr = hasher.hash(input1.to_vec());
|
||||||
let input2: Vec<Fr> = ["0", "0"]
|
let input2: Vec<Fr> = ["0", "0"]
|
||||||
|
|
142
src/public.rs
142
src/public.rs
|
@ -1,8 +1,8 @@
|
||||||
use crate::circuit::poseidon::PoseidonCircuit;
|
|
||||||
use crate::circuit::rln::{RLNCircuit, RLNInputs};
|
use crate::circuit::rln::{RLNCircuit, RLNInputs};
|
||||||
use crate::merkle::MerkleTree;
|
use crate::merkle::MerkleTree;
|
||||||
use crate::poseidon::{Poseidon as PoseidonHasher, PoseidonParams};
|
use crate::poseidon::{Poseidon as PoseidonHasher, PoseidonParams};
|
||||||
use crate::utils::{read_inputs, read_uncompressed_proof, write_uncompressed_proof};
|
use crate::utils::{read_inputs, read_uncompressed_proof, write_uncompressed_proof};
|
||||||
|
use crate::{circuit::poseidon::PoseidonCircuit, merkle::IncrementalMerkleTree};
|
||||||
use bellman::groth16::generate_random_parameters;
|
use bellman::groth16::generate_random_parameters;
|
||||||
use bellman::groth16::{create_proof, prepare_verifying_key, verify_proof};
|
use bellman::groth16::{create_proof, prepare_verifying_key, verify_proof};
|
||||||
use bellman::groth16::{create_random_proof, Parameters, Proof};
|
use bellman::groth16::{create_random_proof, Parameters, Proof};
|
||||||
|
@ -10,7 +10,53 @@ use bellman::pairing::ff::{Field, PrimeField, PrimeFieldRepr};
|
||||||
use bellman::pairing::{CurveAffine, EncodedPoint, Engine};
|
use bellman::pairing::{CurveAffine, EncodedPoint, Engine};
|
||||||
use bellman::{Circuit, ConstraintSystem, SynthesisError};
|
use bellman::{Circuit, ConstraintSystem, SynthesisError};
|
||||||
use rand::{Rand, SeedableRng, XorShiftRng};
|
use rand::{Rand, SeedableRng, XorShiftRng};
|
||||||
use std::io::{self, Error, ErrorKind, Read, Write};
|
use std::{
|
||||||
|
io::{self, Error, ErrorKind, Read, Write},
|
||||||
|
ptr::null,
|
||||||
|
};
|
||||||
|
// Rate Limit Nullifier
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct RLNSignal<E>
|
||||||
|
where
|
||||||
|
E: Engine,
|
||||||
|
{
|
||||||
|
pub epoch: E::Fr,
|
||||||
|
pub hash: E::Fr,
|
||||||
|
pub id_key: E::Fr,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<E> RLNSignal<E>
|
||||||
|
where
|
||||||
|
E: Engine,
|
||||||
|
{
|
||||||
|
pub fn read<R: Read>(mut reader: R) -> io::Result<RLNSignal<E>> {
|
||||||
|
let mut buf = <E::Fr as PrimeField>::Repr::default();
|
||||||
|
|
||||||
|
buf.read_le(&mut reader)?;
|
||||||
|
let hash =
|
||||||
|
E::Fr::from_repr(buf).map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?;
|
||||||
|
buf.read_le(&mut reader)?;
|
||||||
|
let epoch =
|
||||||
|
E::Fr::from_repr(buf).map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?;
|
||||||
|
buf.read_le(&mut reader)?;
|
||||||
|
let id_key =
|
||||||
|
E::Fr::from_repr(buf).map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?;
|
||||||
|
|
||||||
|
Ok(RLNSignal {
|
||||||
|
epoch,
|
||||||
|
hash,
|
||||||
|
id_key,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn write<W: Write>(&self, mut writer: W) -> io::Result<()> {
|
||||||
|
self.epoch.into_repr().write_le(&mut writer).unwrap();
|
||||||
|
self.hash.into_repr().write_le(&mut writer).unwrap();
|
||||||
|
self.id_key.into_repr().write_le(&mut writer).unwrap();
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub struct RLN<E>
|
pub struct RLN<E>
|
||||||
where
|
where
|
||||||
|
@ -18,7 +64,7 @@ where
|
||||||
{
|
{
|
||||||
circuit_parameters: Parameters<E>,
|
circuit_parameters: Parameters<E>,
|
||||||
poseidon_params: PoseidonParams<E>,
|
poseidon_params: PoseidonParams<E>,
|
||||||
merkle_depth: usize,
|
tree: IncrementalMerkleTree<E>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<E> RLN<E>
|
impl<E> RLN<E>
|
||||||
|
@ -41,31 +87,35 @@ where
|
||||||
|
|
||||||
fn new_with_params(
|
fn new_with_params(
|
||||||
merkle_depth: usize,
|
merkle_depth: usize,
|
||||||
|
index: usize,
|
||||||
circuit_parameters: Parameters<E>,
|
circuit_parameters: Parameters<E>,
|
||||||
poseidon_params: PoseidonParams<E>,
|
poseidon_params: PoseidonParams<E>,
|
||||||
) -> RLN<E> {
|
) -> RLN<E> {
|
||||||
|
let hasher = PoseidonHasher::new(poseidon_params.clone());
|
||||||
|
let tree = IncrementalMerkleTree::empty(hasher, merkle_depth, index);
|
||||||
RLN {
|
RLN {
|
||||||
circuit_parameters,
|
circuit_parameters,
|
||||||
poseidon_params,
|
poseidon_params,
|
||||||
merkle_depth,
|
tree,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn poseidon_params(&self) -> PoseidonParams<E> {
|
pub fn new(
|
||||||
self.poseidon_params.clone()
|
merkle_depth: usize,
|
||||||
}
|
index: usize,
|
||||||
|
poseidon_params: Option<PoseidonParams<E>>,
|
||||||
pub fn new(merkle_depth: usize, poseidon_params: Option<PoseidonParams<E>>) -> RLN<E> {
|
) -> RLN<E> {
|
||||||
let poseidon_params = match poseidon_params {
|
let poseidon_params = match poseidon_params {
|
||||||
Some(params) => params,
|
Some(params) => params,
|
||||||
None => Self::default_poseidon_params(),
|
None => Self::default_poseidon_params(),
|
||||||
};
|
};
|
||||||
let circuit_parameters = Self::new_circuit(merkle_depth, poseidon_params.clone());
|
let circuit_parameters = Self::new_circuit(merkle_depth, poseidon_params.clone());
|
||||||
Self::new_with_params(merkle_depth, circuit_parameters, poseidon_params)
|
Self::new_with_params(merkle_depth, index, circuit_parameters, poseidon_params)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_with_raw_params<R: Read>(
|
pub fn new_with_raw_params<R: Read>(
|
||||||
merkle_depth: usize,
|
merkle_depth: usize,
|
||||||
|
index: usize,
|
||||||
raw_circuit_parameters: R,
|
raw_circuit_parameters: R,
|
||||||
poseidon_params: Option<PoseidonParams<E>>,
|
poseidon_params: Option<PoseidonParams<E>>,
|
||||||
) -> io::Result<RLN<E>> {
|
) -> io::Result<RLN<E>> {
|
||||||
|
@ -76,17 +126,31 @@ where
|
||||||
};
|
};
|
||||||
Ok(Self::new_with_params(
|
Ok(Self::new_with_params(
|
||||||
merkle_depth,
|
merkle_depth,
|
||||||
|
index,
|
||||||
circuit_parameters,
|
circuit_parameters,
|
||||||
poseidon_params,
|
poseidon_params,
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn update_next<R: Read>(&mut self, input: R) -> io::Result<()> {
|
||||||
|
let mut buf = <E::Fr as PrimeField>::Repr::default();
|
||||||
|
buf.read_le(input)?;
|
||||||
|
let leaf =
|
||||||
|
E::Fr::from_repr(buf).map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?;
|
||||||
|
self.tree.update_next(leaf);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn poseidon_params(&self) -> PoseidonParams<E> {
|
||||||
|
self.poseidon_params.clone()
|
||||||
|
}
|
||||||
|
|
||||||
pub fn hasher(&self) -> PoseidonHasher<E> {
|
pub fn hasher(&self) -> PoseidonHasher<E> {
|
||||||
PoseidonHasher::new(self.poseidon_params.clone())
|
PoseidonHasher::new(self.poseidon_params.clone())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn hash<R: Read, W: Write>(&self, input: R, n: usize, mut output: W) -> io::Result<()> {
|
pub fn hash<R: Read, W: Write>(&self, input: R, n: usize, mut output: W) -> io::Result<()> {
|
||||||
let mut hasher = self.hasher();
|
let hasher = self.hasher();
|
||||||
let input: Vec<E::Fr> = read_inputs::<R, E>(input, n)?;
|
let input: Vec<E::Fr> = read_inputs::<R, E>(input, n)?;
|
||||||
let result = hasher.hash(input);
|
let result = hasher.hash(input);
|
||||||
// let mut output_data: Vec<u8> = Vec::new();
|
// let mut output_data: Vec<u8> = Vec::new();
|
||||||
|
@ -94,27 +158,61 @@ where
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// input: |epoch<32>|signal_hash<32>|id_key<32>|
|
||||||
|
/// output: |proof<?>|root<32>|epoch<32>|share_x<32>|share_y<32>|nullifier<32>|
|
||||||
pub fn generate_proof<R: Read, W: Write>(&self, input: R, mut output: W) -> io::Result<()> {
|
pub fn generate_proof<R: Read, W: Write>(&self, input: R, mut output: W) -> io::Result<()> {
|
||||||
use rand::chacha::ChaChaRng;
|
use rand::chacha::ChaChaRng;
|
||||||
use rand::SeedableRng;
|
use rand::SeedableRng;
|
||||||
let mut rng = ChaChaRng::new_unseeded();
|
let mut rng = ChaChaRng::new_unseeded();
|
||||||
let inputs = RLNInputs::<E>::read(input)?;
|
let signal = RLNSignal::<E>::read(input)?;
|
||||||
assert_eq!(self.merkle_depth, inputs.merkle_depth());
|
// prepare inputs
|
||||||
let circuit_hasher = PoseidonCircuit::new(self.poseidon_params.clone());
|
|
||||||
|
let hasher = self.hasher();
|
||||||
|
let share_x = signal.hash.clone();
|
||||||
|
|
||||||
|
// line equation
|
||||||
|
let a_0 = signal.id_key.clone();
|
||||||
|
let a_1: E::Fr = hasher.hash(vec![a_0, signal.epoch]);
|
||||||
|
// evaluate line equation
|
||||||
|
let mut share_y = a_1.clone();
|
||||||
|
share_y.mul_assign(&share_x);
|
||||||
|
share_y.add_assign(&a_0);
|
||||||
|
let nullifier = hasher.hash(vec![a_1]);
|
||||||
|
|
||||||
|
let root = self.tree.get_root();
|
||||||
|
let auth_path = self.tree.get_auth_path();
|
||||||
|
|
||||||
|
let inputs = RLNInputs::<E> {
|
||||||
|
share_x: Some(share_x),
|
||||||
|
share_y: Some(share_y),
|
||||||
|
epoch: Some(signal.epoch),
|
||||||
|
nullifier: Some(nullifier),
|
||||||
|
root: Some(root),
|
||||||
|
id_key: Some(signal.id_key),
|
||||||
|
auth_path: auth_path.into_iter().map(|w| Some(w)).collect(),
|
||||||
|
};
|
||||||
|
|
||||||
let circuit = RLNCircuit {
|
let circuit = RLNCircuit {
|
||||||
inputs: inputs.clone(),
|
inputs: inputs.clone(),
|
||||||
hasher: circuit_hasher.clone(),
|
hasher: PoseidonCircuit::new(self.poseidon_params.clone()),
|
||||||
};
|
};
|
||||||
|
|
||||||
let proof = create_random_proof(circuit, &self.circuit_parameters, &mut rng).unwrap();
|
let proof = create_random_proof(circuit, &self.circuit_parameters, &mut rng).unwrap();
|
||||||
write_uncompressed_proof(proof, &mut output)?;
|
write_uncompressed_proof(proof.clone(), &mut output)?;
|
||||||
// proof.write(&mut w).unwrap();
|
root.into_repr().write_le(&mut output)?;
|
||||||
|
signal.epoch.into_repr().write_le(&mut output)?;
|
||||||
|
share_x.into_repr().write_le(&mut output)?;
|
||||||
|
share_y.into_repr().write_le(&mut output)?;
|
||||||
|
nullifier.into_repr().write_le(&mut output)?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn verify<R: Read>(&self, uncompresed_proof: R, raw_public_inputs: R) -> io::Result<bool> {
|
/// proof: |proof<?>|root<32>|epoch<32>|share_x<32>|share_y<32>|nullifier<32>|
|
||||||
let proof = read_uncompressed_proof(uncompresed_proof)?;
|
pub fn verify<R: Read>(&self, mut proof_data: R) -> io::Result<bool> {
|
||||||
// let proof = Proof::read(uncompresed_proof).unwrap();
|
let proof = read_uncompressed_proof(&mut proof_data)?;
|
||||||
let public_inputs = RLNInputs::<E>::read_public_inputs(raw_public_inputs)?;
|
let public_inputs = RLNInputs::<E>::read_public_inputs(&mut proof_data)?;
|
||||||
|
// TODO: root must be checked here
|
||||||
let verifing_key = prepare_verifying_key(&self.circuit_parameters.vk);
|
let verifing_key = prepare_verifying_key(&self.circuit_parameters.vk);
|
||||||
let success = verify_proof(&verifing_key, &proof, &public_inputs).unwrap();
|
let success = verify_proof(&verifing_key, &proof, &public_inputs).unwrap();
|
||||||
Ok(success)
|
Ok(success)
|
||||||
|
@ -122,7 +220,7 @@ where
|
||||||
|
|
||||||
pub fn key_gen<W: Write>(&self, mut w: W) -> io::Result<()> {
|
pub fn key_gen<W: Write>(&self, mut w: W) -> io::Result<()> {
|
||||||
let mut rng = XorShiftRng::from_seed([0x3dbe6258, 0x8d313d76, 0x3237db17, 0xe5bc0654]);
|
let mut rng = XorShiftRng::from_seed([0x3dbe6258, 0x8d313d76, 0x3237db17, 0xe5bc0654]);
|
||||||
let mut hasher = self.hasher();
|
let hasher = self.hasher();
|
||||||
let secret = E::Fr::rand(&mut rng);
|
let secret = E::Fr::rand(&mut rng);
|
||||||
let public: E::Fr = hasher.hash(vec![secret.clone()]);
|
let public: E::Fr = hasher.hash(vec![secret.clone()]);
|
||||||
secret.into_repr().write_le(&mut w)?;
|
secret.into_repr().write_le(&mut w)?;
|
||||||
|
|
Loading…
Reference in New Issue