mirror of https://github.com/status-im/rln.git
add member deletion ffi
This commit is contained in:
parent
1c1fbf402e
commit
c61737e22f
|
@ -91,7 +91,7 @@ where
|
|||
// B. insert to the membership tree
|
||||
|
||||
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
|
||||
|
||||
|
@ -170,6 +170,7 @@ where
|
|||
self.rln
|
||||
.generate_proof(raw_inputs.as_slice(), &mut proof)
|
||||
.unwrap();
|
||||
|
||||
let prover_time = now.elapsed().as_millis() as f64 / 1000.0;
|
||||
|
||||
let mut raw_public_inputs: Vec<u8> = Vec::new();
|
||||
|
|
77
src/ffi.rs
77
src/ffi.rs
|
@ -44,14 +44,22 @@ pub extern "C" fn new_circuit_from_params(
|
|||
}
|
||||
|
||||
#[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 input_data = <&[u8]>::from(unsafe { &*input_buffer });
|
||||
match rln.update_next(input_data) {
|
||||
Ok(proof_data) => proof_data,
|
||||
Err(_) => return false,
|
||||
};
|
||||
true
|
||||
match rln.update_next_member(input_data) {
|
||||
Ok(_) => true,
|
||||
Err(_) => false,
|
||||
}
|
||||
}
|
||||
|
||||
#[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]
|
||||
|
@ -209,35 +217,46 @@ mod tests {
|
|||
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);
|
||||
let success = update_next_member(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,
|
||||
let mut gen_proof_and_verify = |rln_pointer: *const RLN<Bn256>| {
|
||||
// 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();
|
||||
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
|
||||
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() };
|
||||
gen_proof_and_verify(rln_pointer);
|
||||
|
||||
// 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);
|
||||
// delete 0th member
|
||||
let success = delete_member(rln_pointer, 0);
|
||||
assert!(success, "deletion failed");
|
||||
|
||||
// gen proof & verify once more
|
||||
gen_proof_and_verify(rln_pointer);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
|
@ -43,22 +43,15 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
pub fn update_next(&mut self, leaf: E::Fr) {
|
||||
// println!("{}", self.get_root());
|
||||
self.merkle_tree.update(self.current_index, leaf);
|
||||
pub fn update_next(&mut self, leaf: E::Fr) -> io::Result<()> {
|
||||
self.merkle_tree.update(self.current_index, leaf)?;
|
||||
self.current_index += 1;
|
||||
// println!("{}", self.get_root());
|
||||
Ok(())
|
||||
}
|
||||
|
||||
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);
|
||||
self.merkle_tree.update(index, zero)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
@ -132,9 +125,16 @@ where
|
|||
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.recalculate_from(index);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
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 leaf_index = 6;
|
||||
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();
|
||||
assert!(set.check_inclusion(witness, leaf_index).unwrap());
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
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);
|
||||
self.tree.update_next(leaf)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn delete_member(&mut self, index: usize) -> io::Result<()> {
|
||||
self.tree.delete(index)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
@ -149,17 +154,18 @@ where
|
|||
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<()> {
|
||||
let hasher = self.hasher();
|
||||
let input: Vec<E::Fr> = read_inputs::<R, E>(input, n)?;
|
||||
let result = hasher.hash(input);
|
||||
// let mut output_data: Vec<u8> = Vec::new();
|
||||
result.into_repr().write_le(&mut output)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// input: |epoch<32>|signal_hash<32>|id_key<32>|
|
||||
/// output: |proof<?>|root<32>|epoch<32>|share_x<32>|share_y<32>|nullifier<32>|
|
||||
/// 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<()> {
|
||||
use rand::chacha::ChaChaRng;
|
||||
use rand::SeedableRng;
|
||||
|
@ -208,7 +214,8 @@ where
|
|||
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> {
|
||||
let proof = read_uncompressed_proof(&mut proof_data)?;
|
||||
let public_inputs = RLNInputs::<E>::read_public_inputs(&mut proof_data)?;
|
||||
|
@ -218,13 +225,14 @@ where
|
|||
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 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 w)?;
|
||||
public.into_repr().write_le(&mut w)?;
|
||||
secret.into_repr().write_le(&mut output)?;
|
||||
public.into_repr().write_le(&mut output)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue