fn calculate_suids()

in protocol/src/suid_create/merger.rs [288:397]


    fn calculate_suids(&self) -> Result<(), ProtocolError> {
        match (
            self.sharer_pub_key_reuse.clone().read(),
            self.from_shuffler.clone().read(),
            self.to_shuffler.clone().write(),
        ) {
            (Ok(sharer_pub_key_reuse), Ok(from_s), Ok(mut to_s)) => {
                // Decrypt and unflatten keys
                let keys = {
                    // El Gamal decrypt
                    let m = elgamal_decrypt(
                        self.ec_cipher.to_points(&from_s.0),
                        self.ec_cipher.to_points(&from_s.1),
                        self.keypair_m.0,
                    );

                    unflatten_vec(&m, &from_s.2)
                };

                // Generate sets to find SUID
                let mut s_map = HashMap::<Vec<u8>, Vec<usize>>::new();

                // We map every entry in keys to a hash table. Each entry is
                // a vector. We hash each entry in this vector to a hash
                // table entry. The value is the index of this entry. In
                // case of a collision we add the index. Thus we end up with
                // a hashmap of vectors of indices.
                // In subsequent steps we will use the Union Find algorithm
                // to merge intersecting sets
                for (i, e_o) in keys.iter().enumerate() {
                    for e_i in e_o.iter() {
                        let x = e_i.compress().to_bytes().to_vec();
                        let v = s_map.entry(x).or_insert_with(Vec::<usize>::new);
                        v.push(i);
                    }
                }

                // Merge sets created above with union find
                let mut part = UnionFind::new();

                // Make singleton set in union find data structure
                let max_index = keys.len();
                for i in 0..max_index {
                    part.make_group(i);
                }

                // Merge singletons to create sets that are disjoint
                // 1. Iterate over keys in hashmap and retrieve corresponding
                //    vector of indices. By construction this vector has set
                //    property ie all indices within a vector are unique
                // 2. For each index in list, find the root of the tree containing
                //    it in the Union Find data structure. These roots are
                //    collected in a vector called leaders
                // 3. Iterate over leaders to merge the trees corresponding to
                //    the leaders into one tree
                for key in s_map.keys() {
                    let list = s_map.get(key).unwrap();
                    let mut leaders = Vec::<usize>::new();

                    for &x in list.iter() {
                        leaders.push(part.find(x));
                    }

                    // All elements in this list should be in one union
                    if leaders.len() > 1 {
                        for i in (1..leaders.len()).rev() {
                            leaders[0] = part.union(leaders[i], leaders[0]);
                        }
                    }
                }

                // Find leader for indices and project to Ristretto point
                // Note path_to_leader has no path compression - this will likely
                // help parallelization later.
                // Here we convert leader to string to convert it to a RistrettoPoint
                let leaders = {
                    let x = (0..max_index)
                        .collect::<Vec<usize>>()
                        .iter()
                        .map(|&i| {
                            let (leader, _) = part.path_to_leader(i);
                            println!("SHUBHO Debug: leader {}", leader);
                            leader.to_string()
                        })
                        .collect::<Vec<_>>();
                    self.ec_cipher.hash(&x)
                };

                // 2 out of 2 threshold El Gamal - so keys need to be added
                let p_key = self.keypair_reuse.1 + (*sharer_pub_key_reuse);
                let (mut c1_buf, mut c2_buf) = {
                    let (c1, c2) = elgamal_encrypt(leaders, &p_key);
                    (self.ec_cipher.to_bytes(&c1), self.ec_cipher.to_bytes(&c2))
                };

                to_s.0.clear();
                to_s.1.clear();

                to_s.0.append(&mut c1_buf);
                to_s.1.append(&mut c2_buf);
                Ok(())
            }
            _ => {
                error!("Cannot calculate SUID ");
                Err(ProtocolError::ErrorCalculateSUID(
                    "cannot calculate SUID".to_string(),
                ))
            }
        }
    }