use std::collections::HashMap;
use std::collections::HashSet;
use itertools::Itertools;
use tasm_lib::prelude::Digest;
use tasm_lib::prelude::Tip5;
use tasm_lib::twenty_first::util_types::mmr::mmr_membership_proof::MmrMembershipProof;
use super::removal_record::chunk_dictionary::ChunkDictionary;
use super::removal_record::RemovalRecord;
pub const WINDOW_SIZE: u32 = 1 << 20;
pub const CHUNK_SIZE: u32 = 1 << 12;
pub const BATCH_SIZE: u32 = 1 << 3;
pub const NUM_TRIALS: u32 = 45;
pub fn indices_to_hash_map(all_indices: &[u128; NUM_TRIALS as usize]) -> HashMap<u64, Vec<u128>> {
all_indices
.iter()
.map(|bi| ((bi / u128::from(CHUNK_SIZE)) as u64, *bi))
.fold(HashMap::new(), |mut acc, (chunk_index, index)| {
acc.entry(chunk_index).or_default().push(index);
acc
})
}
pub fn get_batch_mutation_argument_for_removal_record(
removal_record: &RemovalRecord,
chunk_dictionaries: &mut [&mut ChunkDictionary],
) -> (HashSet<usize>, Vec<(u64, MmrMembershipProof, Digest)>) {
let mut batch_modification_hash_map: HashMap<u64, (MmrMembershipProof, Digest)> =
HashMap::new();
let mut mutated_chunk_dictionaries: HashSet<usize> = HashSet::new();
for (chunk_index, indices) in &removal_record.get_chunkidx_to_indices_dict() {
for (i, chunk_dictionary) in chunk_dictionaries.iter_mut().enumerate() {
match chunk_dictionary.get_mut(chunk_index) {
Some((mmr_mp, chunk)) => {
for index in indices {
let relative_index = (index % u128::from(CHUNK_SIZE)) as u32;
mutated_chunk_dictionaries.insert(i);
chunk.insert(relative_index);
}
if !batch_modification_hash_map.contains_key(chunk_index) {
batch_modification_hash_map
.insert(*chunk_index, (mmr_mp.to_owned(), Tip5::hash(chunk)));
}
}
None => {
match removal_record.target_chunks.get(chunk_index) {
None => {
}
Some((mp, chunk)) => {
if !batch_modification_hash_map.contains_key(chunk_index) {
let mut target_chunk = chunk.to_owned();
for index in indices {
target_chunk.insert((index % u128::from(CHUNK_SIZE)) as u32);
}
batch_modification_hash_map.insert(
*chunk_index,
(mp.to_owned(), Tip5::hash(&target_chunk)),
);
}
}
};
}
};
}
}
(
mutated_chunk_dictionaries,
batch_modification_hash_map
.into_iter()
.map(|(i, (p, l))| (i, p, l))
.collect(),
)
}
pub fn prepare_authenticated_batch_modification_for_removal_record_reversion(
removal_record: &RemovalRecord,
chunk_dictionaries: &mut [&mut ChunkDictionary],
) -> (HashSet<usize>, Vec<(u64, MmrMembershipProof, Digest)>) {
let mut batch_modification_hash_map: HashMap<u64, (MmrMembershipProof, Digest)> =
HashMap::new();
let mut mutated_chunk_dictionaries: HashSet<usize> = HashSet::new();
for (chunk_index, indices) in &removal_record.get_chunkidx_to_indices_dict() {
for (i, chunk_dictionary) in chunk_dictionaries.iter_mut().enumerate() {
match chunk_dictionary.get_mut(chunk_index) {
Some((mmr_mp, chunk)) => {
for index in indices {
let relative_index = (index % u128::from(CHUNK_SIZE)) as u32;
mutated_chunk_dictionaries.insert(i);
chunk.remove_once(relative_index);
}
if !batch_modification_hash_map.contains_key(chunk_index) {
batch_modification_hash_map
.insert(*chunk_index, (mmr_mp.to_owned(), Tip5::hash(chunk)));
}
}
None => {
match removal_record.target_chunks.get(chunk_index) {
None => {
}
Some((mp, chunk)) => {
if !batch_modification_hash_map.contains_key(chunk_index) {
let target_chunk = chunk.to_owned();
batch_modification_hash_map.insert(
*chunk_index,
(mp.to_owned(), Tip5::hash(&target_chunk)),
);
}
}
};
}
};
}
}
(
mutated_chunk_dictionaries,
batch_modification_hash_map
.iter()
.map(|(i, (p, l))| (*i, p.clone(), *l))
.collect_vec(),
)
}