add member deletion ffi

This commit is contained in:
kilic 2021-02-08 18:56:53 +03:00
parent 1c1fbf402e
commit c61737e22f
4 changed files with 80 additions and 52 deletions

View File

@ -91,7 +91,7 @@ where
// B. insert to the membership tree // B. insert to the membership tree
let id_index = 6; // any number below 2^depth will work let id_index = 6; // any number below 2^depth will work
membership_tree.update(id_index, id_comm); membership_tree.update(id_index, id_comm).unwrap();
// C.1 get membership witness // C.1 get membership witness
@ -170,6 +170,7 @@ where
self.rln self.rln
.generate_proof(raw_inputs.as_slice(), &mut proof) .generate_proof(raw_inputs.as_slice(), &mut proof)
.unwrap(); .unwrap();
let prover_time = now.elapsed().as_millis() as f64 / 1000.0; let prover_time = now.elapsed().as_millis() as f64 / 1000.0;
let mut raw_public_inputs: Vec<u8> = Vec::new(); let mut raw_public_inputs: Vec<u8> = Vec::new();

View File

@ -44,14 +44,22 @@ pub extern "C" fn new_circuit_from_params(
} }
#[no_mangle] #[no_mangle]
pub extern "C" fn update_next(ctx: *mut RLN<Bn256>, input_buffer: *const Buffer) -> bool { pub extern "C" fn update_next_member(ctx: *mut RLN<Bn256>, input_buffer: *const Buffer) -> bool {
let rln = unsafe { &mut *ctx }; let rln = unsafe { &mut *ctx };
let input_data = <&[u8]>::from(unsafe { &*input_buffer }); let input_data = <&[u8]>::from(unsafe { &*input_buffer });
match rln.update_next(input_data) { match rln.update_next_member(input_data) {
Ok(proof_data) => proof_data, Ok(_) => true,
Err(_) => return false, Err(_) => false,
}; }
true }
#[no_mangle]
pub extern "C" fn delete_member(ctx: *mut RLN<Bn256>, index: usize) -> bool {
let rln = unsafe { &mut *ctx };
match rln.delete_member(index) {
Ok(_) => true,
Err(_) => false,
}
} }
#[no_mangle] #[no_mangle]
@ -209,35 +217,46 @@ mod tests {
new_member.into_repr().write_le(&mut input_data).unwrap(); new_member.into_repr().write_le(&mut input_data).unwrap();
let input_buffer = &Buffer::from(input_data.as_ref()); let input_buffer = &Buffer::from(input_data.as_ref());
let success = update_next(rln_pointer, input_buffer); let success = update_next_member(rln_pointer, input_buffer);
assert!(success, "update with new pubkey failed"); assert!(success, "update with new pubkey failed");
} }
// create signal let mut gen_proof_and_verify = |rln_pointer: *const RLN<Bn256>| {
let epoch = Fr::rand(&mut rng); // create signal
let signal_hash = Fr::rand(&mut rng); let epoch = Fr::rand(&mut rng);
let inputs = RLNSignal::<Bn256> { let signal_hash = Fr::rand(&mut rng);
epoch: epoch, let inputs = RLNSignal::<Bn256> {
hash: signal_hash, epoch: epoch,
id_key: id_key, hash: signal_hash,
id_key: id_key,
};
// generate proof
let mut inputs_data: Vec<u8> = Vec::new();
inputs.write(&mut inputs_data).unwrap();
let inputs_buffer = &Buffer::from(inputs_data.as_ref());
let mut proof_buffer = MaybeUninit::<Buffer>::uninit();
let success =
unsafe { generate_proof(rln_pointer, inputs_buffer, 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) };
assert!(success, "verification failed");
assert_eq!(0, result);
}; };
// generate proof gen_proof_and_verify(rln_pointer);
let mut inputs_data: Vec<u8> = Vec::new();
inputs.write(&mut inputs_data).unwrap();
let inputs_buffer = &Buffer::from(inputs_data.as_ref());
let mut proof_buffer = MaybeUninit::<Buffer>::uninit();
let success =
unsafe { generate_proof(rln_pointer, inputs_buffer, proof_buffer.as_mut_ptr()) };
assert!(success, "proof generation failed");
let mut proof_buffer = unsafe { proof_buffer.assume_init() };
// verify proof // delete 0th member
let mut result = 0u32; let success = delete_member(rln_pointer, 0);
let result_ptr = &mut result as *mut u32; assert!(success, "deletion failed");
let success = unsafe { verify(rln_pointer, &mut proof_buffer, result_ptr) };
assert!(success, "verification failed"); // gen proof & verify once more
assert_eq!(0, result); gen_proof_and_verify(rln_pointer);
} }
#[test] #[test]

View File

@ -43,22 +43,15 @@ where
} }
} }
pub fn update_next(&mut self, leaf: E::Fr) { pub fn update_next(&mut self, leaf: E::Fr) -> io::Result<()> {
// println!("{}", self.get_root()); self.merkle_tree.update(self.current_index, leaf)?;
self.merkle_tree.update(self.current_index, leaf);
self.current_index += 1; self.current_index += 1;
// println!("{}", self.get_root()); Ok(())
} }
pub fn delete(&mut self, index: usize) -> io::Result<()> { 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(); let zero = E::Fr::from_str("0").unwrap();
self.merkle_tree.update(index, zero); self.merkle_tree.update(index, zero)?;
Ok(()) Ok(())
} }
@ -132,9 +125,16 @@ where
1 << self.depth 1 << self.depth
} }
pub fn update(&mut self, index: usize, leaf: E::Fr) { pub fn update(&mut self, index: usize, leaf: E::Fr) -> io::Result<()> {
if index >= self.set_size() {
return Err(io::Error::new(
io::ErrorKind::InvalidInput,
"index exceeds set size",
));
}
self.nodes.insert((self.depth, index), leaf); self.nodes.insert((self.depth, index), leaf);
self.recalculate_from(index); self.recalculate_from(index);
Ok(())
} }
pub fn check_inclusion(&self, witness: Vec<(E::Fr, bool)>, index: usize) -> io::Result<bool> { pub fn check_inclusion(&self, witness: Vec<(E::Fr, bool)>, index: usize) -> io::Result<bool> {
@ -229,7 +229,7 @@ fn test_merkle_set() {
let mut set = MerkleTree::empty(hasher.clone(), 3); let mut set = MerkleTree::empty(hasher.clone(), 3);
let leaf_index = 6; let leaf_index = 6;
let leaf = hasher.hash(vec![data[0]]); let leaf = hasher.hash(vec![data[0]]);
set.update(leaf_index, leaf); set.update(leaf_index, leaf).unwrap();
let witness = set.get_witness(leaf_index).unwrap(); let witness = set.get_witness(leaf_index).unwrap();
assert!(set.check_inclusion(witness, leaf_index).unwrap()); assert!(set.check_inclusion(witness, leaf_index).unwrap());
} }

View File

@ -132,12 +132,17 @@ where
)) ))
} }
pub fn update_next<R: Read>(&mut self, input: R) -> io::Result<()> { pub fn update_next_member<R: Read>(&mut self, input: R) -> io::Result<()> {
let mut buf = <E::Fr as PrimeField>::Repr::default(); let mut buf = <E::Fr as PrimeField>::Repr::default();
buf.read_le(input)?; buf.read_le(input)?;
let leaf = let leaf =
E::Fr::from_repr(buf).map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?; E::Fr::from_repr(buf).map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?;
self.tree.update_next(leaf); self.tree.update_next(leaf)?;
Ok(())
}
pub fn delete_member(&mut self, index: usize) -> io::Result<()> {
self.tree.delete(index)?;
Ok(()) Ok(())
} }
@ -149,17 +154,18 @@ where
PoseidonHasher::new(self.poseidon_params.clone()) 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<()> { pub fn hash<R: Read, W: Write>(&self, input: R, n: usize, mut output: W) -> io::Result<()> {
let 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();
result.into_repr().write_le(&mut output)?; result.into_repr().write_le(&mut output)?;
Ok(()) Ok(())
} }
/// input: |epoch<32>|signal_hash<32>|id_key<32>| /// expect `input` serialized as |epoch<32>|signal_hash<32>|id_key<32>|
/// output: |proof<?>|root<32>|epoch<32>|share_x<32>|share_y<32>|nullifier<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<()> { 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;
@ -208,7 +214,8 @@ where
Ok(()) Ok(())
} }
/// proof: |proof<?>|root<32>|epoch<32>|share_x<32>|share_y<32>|nullifier<32>| /// `proof_data` is the proof along with public inputs 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> { pub fn verify<R: Read>(&self, mut proof_data: R) -> io::Result<bool> {
let proof = read_uncompressed_proof(&mut proof_data)?; let proof = read_uncompressed_proof(&mut proof_data)?;
let public_inputs = RLNInputs::<E>::read_public_inputs(&mut proof_data)?; let public_inputs = RLNInputs::<E>::read_public_inputs(&mut proof_data)?;
@ -218,13 +225,14 @@ where
Ok(success) Ok(success)
} }
pub fn key_gen<W: Write>(&self, mut w: W) -> io::Result<()> { /// `output` is seralized as |secret<32>|public<32>|
pub fn key_gen<W: Write>(&self, mut output: W) -> io::Result<()> {
let mut rng = XorShiftRng::from_seed([0x3dbe6258, 0x8d313d76, 0x3237db17, 0xe5bc0654]); let mut rng = XorShiftRng::from_seed([0x3dbe6258, 0x8d313d76, 0x3237db17, 0xe5bc0654]);
let 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 output)?;
public.into_repr().write_le(&mut w)?; public.into_repr().write_le(&mut output)?;
Ok(()) Ok(())
} }