diff --git a/core/src/core/pmmr/backend.rs b/core/src/core/pmmr/backend.rs index 5159c4277..6118a8b2e 100644 --- a/core/src/core/pmmr/backend.rs +++ b/core/src/core/pmmr/backend.rs @@ -27,7 +27,7 @@ pub trait Backend { /// associated data element to flatfile storage (for leaf nodes only). The /// position of the first element of the Vec in the MMR is provided to /// help the implementation. - fn append(&mut self, data: &T, hashes: Vec) -> Result<(), String>; + fn append(&mut self, data: &T, hashes: &[Hash]) -> Result<(), String>; /// Rewind the backend state to a previous position, as if all append /// operations after that had been canceled. Expects a position in the PMMR diff --git a/core/src/core/pmmr/pmmr.rs b/core/src/core/pmmr/pmmr.rs index 1e8cb199a..c0591c9b9 100644 --- a/core/src/core/pmmr/pmmr.rs +++ b/core/src/core/pmmr/pmmr.rs @@ -237,7 +237,7 @@ where } // append all the new nodes and update the MMR index - self.backend.append(elmt, hashes)?; + self.backend.append(elmt, &hashes)?; self.last_pos = pos; Ok(elmt_pos) } diff --git a/core/src/core/pmmr/vec_backend.rs b/core/src/core/pmmr/vec_backend.rs index fea1dbe63..00fcad55d 100644 --- a/core/src/core/pmmr/vec_backend.rs +++ b/core/src/core/pmmr/vec_backend.rs @@ -35,11 +35,11 @@ pub struct VecBackend { } impl Backend for VecBackend { - fn append(&mut self, elmt: &T, hashes: Vec) -> Result<(), String> { + fn append(&mut self, elmt: &T, hashes: &[Hash]) -> Result<(), String> { if let Some(data) = &mut self.data { data.push(elmt.clone()); } - self.hashes.append(&mut hashes.clone()); + self.hashes.extend_from_slice(hashes); Ok(()) } diff --git a/store/src/pmmr.rs b/store/src/pmmr.rs index 84ce07b5a..269afbb11 100644 --- a/store/src/pmmr.rs +++ b/store/src/pmmr.rs @@ -66,17 +66,15 @@ impl Backend for PMMRBackend { /// Append the provided data and hashes to the backend storage. /// Add the new leaf pos to our leaf_set if this is a prunable MMR. #[allow(unused_variables)] - fn append(&mut self, data: &T, hashes: Vec) -> Result<(), String> { + fn append(&mut self, data: &T, hashes: &[Hash]) -> Result<(), String> { let size = self .data_file .append(&data.as_elmt()) .map_err(|e| format!("Failed to append data to file. {}", e))?; - for h in &hashes { - self.hash_file - .append(h) - .map_err(|e| format!("Failed to append hash to file. {}", e))?; - } + self.hash_file + .extend_from_slice(hashes) + .map_err(|e| format!("Failed to append hash to file. {}", e))?; if self.prunable { // (Re)calculate the latest pos given updated size of data file diff --git a/store/src/types.rs b/store/src/types.rs index 7dddff1e0..df21a1719 100644 --- a/store/src/types.rs +++ b/store/src/types.rs @@ -99,6 +99,14 @@ where Ok(self.size_unsync()) } + /// Append a slice of multiple elements to the file. + /// Will not be written to disk until flush() is subsequently called. + /// Alternatively discard() may be called to discard any pending changes. + pub fn extend_from_slice(&mut self, data: &[T]) -> io::Result { + self.file.append_elmts(data)?; + Ok(self.size_unsync()) + } + /// Read an element from the file by position. /// Assumes we have already "shifted" the position to account for pruned data. /// Note: PMMR API is 1-indexed, but backend storage is 0-indexed. @@ -280,6 +288,14 @@ where Ok(()) } + /// Iterate over the slice and append each element. + fn append_elmts(&mut self, data: &[T]) -> io::Result<()> { + for x in data { + self.append_elmt(x)?; + } + Ok(()) + } + /// Append data to the file. Until the append-only file is synced, data is /// only written to memory. pub fn append(&mut self, bytes: &mut [u8]) -> io::Result<()> {