feat: batch ops

This commit is contained in:
rymnc 2023-05-09 13:46:38 +05:30
parent b3a02216ce
commit 93ccd0b594
No known key found for this signature in database
GPG Key ID: C740033EE3F41EBD
2 changed files with 101 additions and 0 deletions

View File

@ -250,6 +250,62 @@ where
Ok(())
}
pub fn batch_operations<I: IntoIterator<Item = H::Fr>, J: IntoIterator<Item = usize>>(
&mut self,
leaves: I,
to_remove_indices: J,
) -> PmtreeResult<()> {
let leaves = leaves.into_iter().collect::<Vec<_>>();
let to_remove_indices = to_remove_indices.into_iter().collect::<Vec<_>>();
let start = self.next_index;
let end = start + leaves.len();
if end - to_remove_indices.len() > self.capacity() {
return Err(PmtreeErrorKind::TreeError(TreeErrorKind::MerkleTreeIsFull));
}
let mut subtree = HashMap::<Key, H::Fr>::new();
let root_key = Key(0, 0);
subtree.insert(root_key, self.root);
self.fill_nodes(root_key, start, end, &mut subtree, &leaves, start)?;
for i in to_remove_indices {
subtree.insert(Key(self.depth, i), H::default_leaf());
}
let subtree = Arc::new(RwLock::new(subtree));
let root_val = rayon::ThreadPoolBuilder::new()
.num_threads(rayon::current_num_threads())
.build()
.unwrap()
.install(|| Self::batch_recalculate(root_key, Arc::clone(&subtree), self.depth));
let subtree = RwLock::into_inner(Arc::try_unwrap(subtree).unwrap()).unwrap();
self.db.put_batch(
subtree
.into_iter()
.map(|(key, value)| (key.into(), H::serialize(value)))
.collect(),
)?;
// Update next_index value in db
if end > self.next_index {
self.next_index = end;
self.db
.put(NEXT_INDEX_KEY, self.next_index.to_be_bytes().to_vec())?;
}
// Update root value in memory
self.root = root_val;
Ok(())
}
// Fills hashmap subtree
fn fill_nodes(
&self,

View File

@ -196,3 +196,48 @@ fn set_range() -> PmtreeResult<()> {
Ok(())
}
#[test]
fn batch_operations() -> PmtreeResult<()> {
let mut mt = MerkleTree::<MySled, MyKeccak>::new(
2,
SledConfig {
path: String::from("batch_operations"),
},
)?;
let leaves = [
hex!("0000000000000000000000000000000000000000000000000000000000000001"),
hex!("0000000000000000000000000000000000000000000000000000000000000002"),
];
mt.batch_insert(None, &leaves)?;
assert_eq!(
mt.root(),
hex!("893760ec5b5bee236f29e85aef64f17139c3c1b7ff24ce64eb6315fca0f2485b")
);
let leaves = [
hex!("0000000000000000000000000000000000000000000000000000000000000003"),
hex!("0000000000000000000000000000000000000000000000000000000000000004"),
];
mt.batch_operations(leaves, [])?;
assert_eq!(
mt.root(),
hex!("a9bb8c3f1f12e9aa903a50c47f314b57610a3ab32f2d463293f58836def38d36")
);
mt.batch_operations([], [0, 1, 2, 3])?;
assert_eq!(
mt.root(),
hex!("b4c11951957c6f8f642c4af61cd6b24640fec6dc7fc607ee8206a99e92410d30")
);
fs::remove_dir_all("batch_operations").expect("Error removing db");
Ok(())
}