move member index to auth object

This commit is contained in:
kilic 2021-02-09 13:01:30 +03:00
parent c61737e22f
commit a80f5d013e
5 changed files with 194 additions and 125 deletions

View File

@ -1,17 +1,17 @@
use crate::circuit::poseidon::PoseidonCircuit;
use crate::circuit::rln::{RLNCircuit, RLNInputs};
use crate::merkle::MerkleTree;
use crate::poseidon::{Poseidon as PoseidonHasher, PoseidonParams};
use crate::{circuit::poseidon::PoseidonCircuit, public::RLNSignal};
use rand::{Rand, SeedableRng, XorShiftRng};
use sapling_crypto::bellman::groth16::*;
use sapling_crypto::bellman::pairing::ff::{Field, PrimeField, PrimeFieldRepr};
use sapling_crypto::bellman::pairing::Engine;
use sapling_crypto::bellman::Circuit;
use sapling_crypto::circuit::test::TestConstraintSystem;
use std::error::Error;
use std::io::{self, ErrorKind, Read, Write};
use std::thread::sleep;
use std::time::{Duration, Instant};
use std::{error::Error, hash::Hash};
use crate::public::RLN;
@ -52,23 +52,29 @@ where
XorShiftRng::from_seed([0x3dbe6258, 0x8d313d76, 0x3237db17, 0xe5bc0654])
}
fn empty_inputs(merkle_depth: usize) -> RLNInputs<E> {
RLNInputs::<E> {
share_x: None,
share_y: None,
epoch: None,
nullifier: None,
root: None,
id_key: None,
auth_path: vec![None; merkle_depth],
}
fn secret_key() -> E::Fr {
E::Fr::from_str("1001").unwrap()
}
fn insert_public_key(&mut self) {
let hasher = self.hasher();
let public_key = hasher.hash(vec![Self::secret_key()]);
let mut pubkey_data: Vec<u8> = Vec::new();
public_key.into_repr().write_le(&mut pubkey_data).unwrap();
self.rln.update_next_member(pubkey_data.as_slice()).unwrap();
}
fn id_index() -> usize {
0
}
pub fn new(merkle_depth: usize, poseidon_params: Option<PoseidonParams<E>>) -> RLNTest<E> {
RLNTest {
rln: RLN::new(merkle_depth, 0, poseidon_params),
let mut rln_test = RLNTest {
rln: RLN::new(merkle_depth, poseidon_params),
merkle_depth,
}
};
rln_test.insert_public_key();
rln_test
}
pub fn hasher(&self) -> PoseidonHasher<E> {
@ -85,8 +91,8 @@ where
// A. setup an identity
let id_key = E::Fr::rand(&mut rng);
let id_comm: E::Fr = hasher.hash(vec![id_key.clone()]);
let secret_key = E::Fr::rand(&mut rng);
let id_comm: E::Fr = hasher.hash(vec![secret_key.clone()]);
// B. insert to the membership tree
@ -110,7 +116,7 @@ where
let share_x = signal_hash.clone();
// calculate current line equation
let a_0 = id_key.clone();
let a_0 = secret_key.clone();
let a_1: E::Fr = hasher.hash(vec![a_0, epoch]);
// evaluate line equation
@ -129,15 +135,27 @@ where
epoch: Some(epoch),
nullifier: Some(nullifier),
root: Some(membership_tree.get_root()),
id_key: Some(id_key),
id_key: Some(secret_key),
auth_path: auth_path.into_iter().map(|w| Some(w)).collect(),
};
inputs
}
pub fn signal(&self) -> RLNSignal<E> {
let mut rng = Self::rng();
let epoch = E::Fr::rand(&mut rng);
let signal_hash = E::Fr::rand(&mut rng);
RLNSignal {
epoch,
hash: signal_hash,
}
}
pub fn synthesize(&self) -> usize {
let hasher = PoseidonCircuit::new(self.rln.poseidon_params());
println!("{}", self.merkle_depth);
let inputs = self.valid_inputs();
let circuit = RLNCircuit::<E> {
inputs: inputs.clone(),
@ -147,7 +165,12 @@ where
let mut cs = TestConstraintSystem::<E>::new();
let circuit = circuit.clone();
circuit.synthesize(&mut cs).unwrap();
match circuit.synthesize(&mut cs) {
Ok(_) => (),
Err(e) => {
println!("err\n{}", e);
}
}
let unsatisfied = cs.which_is_unsatisfied();
if unsatisfied.is_some() {
panic!("unsatisfied\n{}", unsatisfied.unwrap());
@ -161,27 +184,33 @@ where
}
pub fn run_prover_bench(&self) -> ProverBenchResult {
let mut raw_inputs: Vec<u8> = Vec::new();
let inputs = self.valid_inputs();
inputs.write(&mut raw_inputs).unwrap();
let mut signal_data: Vec<u8> = Vec::new();
let signal = self.signal();
signal.write(&mut signal_data).unwrap();
let mut proof: Vec<u8> = Vec::new();
let now = Instant::now();
let mut secret_key_data: Vec<u8> = Vec::new();
let secret_key = Self::secret_key();
secret_key
.into_repr()
.write_le(&mut secret_key_data)
.unwrap();
let id_index = Self::id_index();
self.rln
.generate_proof(raw_inputs.as_slice(), &mut proof)
.generate_proof(
signal_data.as_slice(),
secret_key_data.as_slice(),
id_index,
&mut proof,
)
.unwrap();
let prover_time = now.elapsed().as_millis() as f64 / 1000.0;
let mut raw_public_inputs: Vec<u8> = Vec::new();
inputs.write_public_inputs(&mut raw_public_inputs).unwrap();
// assert!(
// self.rln
// .verify(proof.as_slice(), raw_public_inputs.as_slice())
// .unwrap(),
// true
// );
assert!(self.rln.verify(proof.as_slice()).unwrap(), true);
let mut circuit_parameters: Vec<u8> = Vec::new();
self.rln

View File

@ -26,16 +26,28 @@ impl<'a> From<&Buffer> for &'a [u8] {
unsafe { slice::from_raw_parts(src.ptr, src.len) }
}
}
#[repr(C)]
#[derive(Clone, Debug, PartialEq)]
pub struct Auth {
secret_buffer: *const Buffer,
pub index: usize,
}
impl Auth {
fn get_secret(&self) -> &[u8] {
let secret_data = <&[u8]>::from(unsafe { &*self.secret_buffer });
secret_data
}
}
#[no_mangle]
pub extern "C" fn new_circuit_from_params(
merkle_depth: usize,
index: usize,
parameters_buffer: *const Buffer,
ctx: *mut *mut RLN<Bn256>,
) -> bool {
let buffer = <&[u8]>::from(unsafe { &*parameters_buffer });
let rln = match RLN::<Bn256>::new_with_raw_params(merkle_depth, index, buffer, None) {
let rln = match RLN::<Bn256>::new_with_raw_params(merkle_depth, buffer, None) {
Ok(rln) => rln,
Err(_) => return false,
};
@ -66,12 +78,15 @@ pub extern "C" fn delete_member(ctx: *mut RLN<Bn256>, index: usize) -> bool {
pub extern "C" fn generate_proof(
ctx: *const RLN<Bn256>,
input_buffer: *const Buffer,
auth: *const Auth,
output_buffer: *mut Buffer,
) -> bool {
let rln = unsafe { &*ctx };
let auth = unsafe { &*auth };
let input_data = <&[u8]>::from(unsafe { &*input_buffer });
let mut output_data: Vec<u8> = Vec::new();
match rln.generate_proof(input_data, &mut output_data) {
match rln.generate_proof(input_data, auth.get_secret(), auth.index, &mut output_data) {
Ok(proof_data) => proof_data,
Err(_) => return false,
};
@ -103,14 +118,13 @@ pub extern "C" fn verify(
pub extern "C" fn hash(
ctx: *const RLN<Bn256>,
inputs_buffer: *const Buffer,
input_len: *const usize,
input_len: usize,
output_buffer: *mut Buffer,
) -> bool {
let rln = unsafe { &*ctx };
let input_data = <&[u8]>::from(unsafe { &*inputs_buffer });
let n: usize = unsafe { *input_len };
let mut output_data: Vec<u8> = Vec::new();
match rln.hash(input_data, n, &mut output_data) {
match rln.hash(input_data, input_len, &mut output_data) {
Ok(output_data) => output_data,
Err(_) => return false,
};
@ -164,17 +178,14 @@ mod tests {
fn rln_pointer(circuit_parameters: Vec<u8>) -> MaybeUninit<*mut RLN<Bn256>> {
// restore this new curcuit with bindings
let merkle_depth = merkle_depth();
let index = index();
let circuit_parameters_buffer = &Buffer::from(circuit_parameters.as_ref());
let mut rln_pointer = MaybeUninit::<*mut RLN<Bn256>>::uninit();
unsafe {
new_circuit_from_params(
merkle_depth,
index,
circuit_parameters_buffer,
rln_pointer.as_mut_ptr(),
)
};
let success = new_circuit_from_params(
merkle_depth,
circuit_parameters_buffer,
rln_pointer.as_mut_ptr(),
);
assert!(success, "cannot init rln instance");
rln_pointer
}
@ -195,10 +206,12 @@ mod tests {
// generate new key pair
let mut keypair_buffer = MaybeUninit::<Buffer>::uninit();
let success = unsafe { key_gen(rln_pointer, keypair_buffer.as_mut_ptr()) };
let success = 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);
// read keypair
let mut buf = <Fr as PrimeField>::Repr::default();
buf.read_le(&mut keypair_data).unwrap();
let id_key = Fr::from_repr(buf).unwrap();
@ -228,23 +241,33 @@ mod tests {
let inputs = RLNSignal::<Bn256> {
epoch: epoch,
hash: signal_hash,
id_key: id_key,
};
// generate proof
// serialize signal
let mut inputs_data: Vec<u8> = Vec::new();
inputs.write(&mut inputs_data).unwrap();
let inputs_buffer = &Buffer::from(inputs_data.as_ref());
// construct auth object
let mut secret_data: Vec<u8> = Vec::new();
id_key.into_repr().write_le(&mut secret_data).unwrap();
let secret_buffer = &Buffer::from(secret_data.as_ref());
let auth = &Auth {
secret_buffer,
index,
} as *const Auth;
// generate proof
let mut proof_buffer = MaybeUninit::<Buffer>::uninit();
let success =
unsafe { generate_proof(rln_pointer, inputs_buffer, proof_buffer.as_mut_ptr()) };
generate_proof(rln_pointer, inputs_buffer, auth, proof_buffer.as_mut_ptr());
assert!(success, "proof generation failed");
let mut proof_buffer = unsafe { proof_buffer.assume_init() };
// verify proof
let mut result = 0u32;
let result_ptr = &mut result as *mut u32;
let success = unsafe { verify(rln_pointer, &mut proof_buffer, result_ptr) };
let success = verify(rln_pointer, &mut proof_buffer, result_ptr);
assert!(success, "verification failed");
assert_eq!(0, result);
};
@ -281,7 +304,6 @@ mod tests {
let input_buffer = &Buffer::from(input_data.as_ref());
let input_len: usize = 2;
let input_len_pointer = &input_len as *const usize;
let expected = hasher.hash(inputs);
let mut expected_data: Vec<u8> = Vec::new();
@ -289,14 +311,13 @@ mod tests {
let mut result_buffer = MaybeUninit::<Buffer>::uninit();
let success = unsafe {
hash(
rln_pointer,
input_buffer,
input_len_pointer,
result_buffer.as_mut_ptr(),
)
};
let success = hash(
rln_pointer,
input_buffer,
input_len,
result_buffer.as_mut_ptr(),
);
assert!(success, "hash ffi call failed");
let result_buffer = unsafe { result_buffer.assume_init() };
@ -319,7 +340,7 @@ mod tests {
let mut keypair_buffer = MaybeUninit::<Buffer>::uninit();
let success = unsafe { key_gen(rln_pointer, keypair_buffer.as_mut_ptr()) };
let success = key_gen(rln_pointer, keypair_buffer.as_mut_ptr());
assert!(success, "proof generation failed");
let keypair_buffer = unsafe { keypair_buffer.assume_init() };
@ -334,4 +355,21 @@ mod tests {
assert_eq!(public, expected_public);
}
#[test]
#[ignore]
fn test_parameters_from_file() {
use hex;
use std::fs;
let data = fs::read("./parameters.key").expect("Unable to read file");
let merkle_depth = merkle_depth();
let circuit_parameters_buffer = &Buffer::from(data.as_ref());
let mut rln_pointer = MaybeUninit::<*mut RLN<Bn256>>::uninit();
let success = new_circuit_from_params(
merkle_depth,
circuit_parameters_buffer,
rln_pointer.as_mut_ptr(),
);
assert!(success, "creating failed");
}
}

View File

@ -13,7 +13,6 @@ pub struct IncrementalMerkleTree<E>
where
E: Engine,
{
pub self_index: usize,
pub current_index: usize,
merkle_tree: MerkleTree<E>,
}
@ -22,7 +21,7 @@ impl<E> IncrementalMerkleTree<E>
where
E: Engine,
{
pub fn empty(hasher: Hasher<E>, depth: usize, self_index: usize) -> Self {
pub fn empty(hasher: Hasher<E>, depth: 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 {
@ -37,7 +36,6 @@ where
};
let current_index: usize = 0;
IncrementalMerkleTree {
self_index,
current_index,
merkle_tree,
}
@ -65,10 +63,6 @@ where
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)
}

View File

@ -1,7 +1,7 @@
use crate::circuit::rln::{RLNCircuit, RLNInputs};
use crate::merkle::MerkleTree;
use crate::poseidon::{Poseidon as PoseidonHasher, PoseidonParams};
use crate::utils::{read_inputs, read_uncompressed_proof, write_uncompressed_proof};
use crate::utils::{read_fr, read_uncompressed_proof, write_uncompressed_proof};
use crate::{circuit::poseidon::PoseidonCircuit, merkle::IncrementalMerkleTree};
use bellman::groth16::generate_random_parameters;
use bellman::groth16::{create_proof, prepare_verifying_key, verify_proof};
@ -23,7 +23,6 @@ where
{
pub epoch: E::Fr,
pub hash: E::Fr,
pub id_key: E::Fr,
}
impl<E> RLNSignal<E>
@ -39,21 +38,13 @@ where
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,
})
Ok(RLNSignal { epoch, hash })
}
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(())
}
}
@ -87,12 +78,11 @@ where
fn new_with_params(
merkle_depth: usize,
index: usize,
circuit_parameters: Parameters<E>,
poseidon_params: PoseidonParams<E>,
) -> RLN<E> {
let hasher = PoseidonHasher::new(poseidon_params.clone());
let tree = IncrementalMerkleTree::empty(hasher, merkle_depth, index);
let tree = IncrementalMerkleTree::empty(hasher, merkle_depth);
RLN {
circuit_parameters,
poseidon_params,
@ -100,22 +90,17 @@ where
}
}
pub fn new(
merkle_depth: usize,
index: usize,
poseidon_params: Option<PoseidonParams<E>>,
) -> RLN<E> {
pub fn new(merkle_depth: usize, poseidon_params: Option<PoseidonParams<E>>) -> RLN<E> {
let poseidon_params = match poseidon_params {
Some(params) => params,
None => Self::default_poseidon_params(),
};
let circuit_parameters = Self::new_circuit(merkle_depth, poseidon_params.clone());
Self::new_with_params(merkle_depth, index, circuit_parameters, poseidon_params)
Self::new_with_params(merkle_depth, circuit_parameters, poseidon_params)
}
pub fn new_with_raw_params<R: Read>(
merkle_depth: usize,
index: usize,
raw_circuit_parameters: R,
poseidon_params: Option<PoseidonParams<E>>,
) -> io::Result<RLN<E>> {
@ -126,58 +111,69 @@ where
};
Ok(Self::new_with_params(
merkle_depth,
index,
circuit_parameters,
poseidon_params,
))
}
pub fn update_next_member<R: Read>(&mut self, input: R) -> io::Result<()> {
//// inserts new member with given public key
/// * `public_key_data` is a 32 scalar field element in 32 bytes
pub fn update_next_member<R: Read>(&mut self, public_key_data: R) -> io::Result<()> {
let mut buf = <E::Fr as PrimeField>::Repr::default();
buf.read_le(input)?;
buf.read_le(public_key_data)?;
let leaf =
E::Fr::from_repr(buf).map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?;
self.tree.update_next(leaf)?;
Ok(())
}
//// deletes member with given index
pub fn delete_member(&mut self, index: usize) -> io::Result<()> {
self.tree.delete(index)?;
Ok(())
}
pub fn poseidon_params(&self) -> PoseidonParams<E> {
self.poseidon_params.clone()
}
pub fn hasher(&self) -> PoseidonHasher<E> {
PoseidonHasher::new(self.poseidon_params.clone())
}
/// expect one or two scalar field element in 32 bytes in `input`
/// `output` is a 32 scalar field element in 32 bytes
pub fn hash<R: Read, W: Write>(&self, input: R, n: usize, mut output: W) -> io::Result<()> {
/// hashes scalar field elements
/// * expect numbers of scalar field element in 32 bytes in `input_data`
/// * expect `result_data` is a scalar field element in 32 bytes
/// * `n` is number of scalar field elemends stored in `input`
pub fn hash<R: Read, W: Write>(
&self,
input_data: R,
n: usize,
mut result_data: W,
) -> io::Result<()> {
let hasher = self.hasher();
let input: Vec<E::Fr> = read_inputs::<R, E>(input, n)?;
let input: Vec<E::Fr> = read_fr::<R, E>(input_data, n)?;
let result = hasher.hash(input);
result.into_repr().write_le(&mut output)?;
result.into_repr().write_le(&mut result_data)?;
Ok(())
}
/// expect `input` serialized as |epoch<32>|signal_hash<32>|id_key<32>|
/// `output` is proof data serialized as |proof<416>|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<()> {
/// given public inputs and autharization data generates public inputs and proof
/// * expect `input` serialized as |epoch<32>|signal_hash<32>|
/// * expect `id_key_data` is a scalar field element in 32 bytes
/// * `output_data` is proof data serialized as |proof<416>|root<32>|epoch<32>|share_x<32>|share_y<32>|nullifier<32>|
pub fn generate_proof<R: Read, W: Write>(
&self,
input_data: R,
id_key_data: R,
member_index: usize,
mut output_data: W,
) -> io::Result<()> {
use rand::chacha::ChaChaRng;
use rand::SeedableRng;
let mut rng = ChaChaRng::new_unseeded();
let signal = RLNSignal::<E>::read(input)?;
let signal = RLNSignal::<E>::read(input_data)?;
// prepare inputs
let hasher = self.hasher();
let share_x = signal.hash.clone();
let id_key: E::Fr = read_fr::<R, E>(id_key_data, 1)?[0];
// line equation
let a_0 = signal.id_key.clone();
let a_0 = 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();
@ -186,7 +182,8 @@ where
let nullifier = hasher.hash(vec![a_1]);
let root = self.tree.get_root();
let auth_path = self.tree.get_auth_path();
// TODO: check id key here
let auth_path = self.tree.get_witness(member_index)?;
let inputs = RLNInputs::<E> {
share_x: Some(share_x),
@ -194,7 +191,7 @@ where
epoch: Some(signal.epoch),
nullifier: Some(nullifier),
root: Some(root),
id_key: Some(signal.id_key),
id_key: Some(id_key),
auth_path: auth_path.into_iter().map(|w| Some(w)).collect(),
};
@ -203,18 +200,20 @@ where
hasher: PoseidonCircuit::new(self.poseidon_params.clone()),
};
// TOOD: handle create proof error
let proof = create_random_proof(circuit, &self.circuit_parameters, &mut rng).unwrap();
write_uncompressed_proof(proof.clone(), &mut output)?;
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)?;
write_uncompressed_proof(proof.clone(), &mut output_data)?;
root.into_repr().write_le(&mut output_data)?;
signal.epoch.into_repr().write_le(&mut output_data)?;
share_x.into_repr().write_le(&mut output_data)?;
share_y.into_repr().write_le(&mut output_data)?;
nullifier.into_repr().write_le(&mut output_data)?;
Ok(())
}
/// `proof_data` is the proof along with public inputs serialized as:
/// given proof and public data verifies the signal
/// * expect `proof_data` is serialized as:
/// |proof<416>|root<32>|epoch<32>|share_x<32>|share_y<32>|nullifier<32>|
pub fn verify<R: Read>(&self, mut proof_data: R) -> io::Result<bool> {
let proof = read_uncompressed_proof(&mut proof_data)?;
@ -225,14 +224,15 @@ where
Ok(success)
}
/// `output` is seralized as |secret<32>|public<32>|
pub fn key_gen<W: Write>(&self, mut output: W) -> io::Result<()> {
/// generates public private key pair
/// * `key_pair_data` is seralized as |secret<32>|public<32>|
pub fn key_gen<W: Write>(&self, mut key_pair_data: W) -> io::Result<()> {
let mut rng = XorShiftRng::from_seed([0x3dbe6258, 0x8d313d76, 0x3237db17, 0xe5bc0654]);
let hasher = self.hasher();
let secret = E::Fr::rand(&mut rng);
let public: E::Fr = hasher.hash(vec![secret.clone()]);
secret.into_repr().write_le(&mut output)?;
public.into_repr().write_le(&mut output)?;
secret.into_repr().write_le(&mut key_pair_data)?;
public.into_repr().write_le(&mut key_pair_data)?;
Ok(())
}
@ -243,4 +243,12 @@ where
pub fn export_circuit_parameters<W: Write>(&self, w: W) -> io::Result<()> {
self.circuit_parameters.write(w)
}
pub fn hasher(&self) -> PoseidonHasher<E> {
PoseidonHasher::new(self.poseidon_params.clone())
}
pub fn poseidon_params(&self) -> PoseidonParams<E> {
self.poseidon_params.clone()
}
}

View File

@ -5,7 +5,7 @@ use bellman::pairing::{CurveAffine, EncodedPoint, Engine};
use rand::{Rand, SeedableRng, XorShiftRng};
use std::io::{self, Error, ErrorKind, Read, Write};
pub fn read_inputs<R: Read, E: Engine>(mut reader: R, n: usize) -> io::Result<Vec<E::Fr>> {
pub fn read_fr<R: Read, E: Engine>(mut reader: R, n: usize) -> io::Result<Vec<E::Fr>> {
let mut out: Vec<E::Fr> = Vec::new();
let mut buf = <E::Fr as PrimeField>::Repr::default();
for _ in 0..n {