Skip to content

Commit f71b89c

Browse files
[commonware-storage/bitmap] minor authenticated bitmap cleanup (#749)
1 parent b9c5957 commit f71b89c

1 file changed

Lines changed: 28 additions & 20 deletions

File tree

storage/src/mmr/bitmap.rs

Lines changed: 28 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -37,12 +37,14 @@ pub struct Bitmap<H: CHasher> {
3737
/// The bitmap itself, in chunks of size DIGEST_SIZE bytes. The number of valid bits in the last
3838
/// chunk is given by `self.next_bit`. Within each byte, lowest order bits are treated as coming
3939
/// before higher order bits in the bit ordering.
40+
///
41+
/// Invariant: The last chunk in the bitmap always has room for at least one more bit.
4042
bitmap: Vec<u8>,
4143

4244
/// The position within the last chunk of the bitmap where the next bit is to be appended.
4345
///
4446
/// Invariant: This value is always in the range [0, DIGEST_SIZE * 8).
45-
next_bit: usize,
47+
next_bit: u64,
4648

4749
/// A Merkle tree with each leaf representing DIGEST_SIZE*8 bits of the bitmap.
4850
///
@@ -61,7 +63,11 @@ impl<H: CHasher> Default for Bitmap<H> {
6163
}
6264

6365
impl<H: CHasher> Bitmap<H> {
64-
const CHUNK_SIZE: usize = H::Digest::SIZE;
66+
/// The size of a chunk in bytes.
67+
pub const CHUNK_SIZE: usize = H::Digest::SIZE;
68+
69+
/// The size of a chunk in bits.
70+
const CHUNK_SIZE_BITS: u64 = Self::CHUNK_SIZE as u64 * 8;
6571

6672
/// Return a new empty bitmap.
6773
pub fn new() -> Self {
@@ -79,14 +85,13 @@ impl<H: CHasher> Bitmap<H> {
7985

8086
/// Return the number of bits currently stored in the bitmap, irrespective of any pruning.
8187
pub fn bit_count(&self) -> u64 {
82-
((self.pruned_bytes() + self.bitmap.len()) * 8 - Self::CHUNK_SIZE * 8 + self.next_bit)
83-
as u64
88+
(self.pruned_bytes() + self.bitmap.len()) as u64 * 8 - Self::CHUNK_SIZE_BITS + self.next_bit
8489
}
8590

8691
/// Prune the bitmap to the most recent chunk boundary that contains the referenced bit. Panics
8792
/// if the referenced bit has been pruned or is greater than the number of bits in the bitmap.
8893
pub fn prune_to_bit(&mut self, bit_offset: u64) {
89-
let chunk_pos = bit_offset as usize / 8 / Self::CHUNK_SIZE;
94+
let chunk_pos = Self::chunk_pos(bit_offset);
9095
let mut byte_offset = chunk_pos * Self::CHUNK_SIZE;
9196
let pruned_bytes = self.pruned_bytes();
9297
assert!(byte_offset >= pruned_bytes, "bit pruned");
@@ -110,7 +115,7 @@ impl<H: CHasher> Bitmap<H> {
110115
/// Returns the bitmap chunk containing the specified bit as a digest. Panics if the bit doesn't
111116
/// exist or has been pruned.
112117
fn get_chunk(&self, bit_offset: u64) -> H::Digest {
113-
let mut byte_offset = bit_offset as usize / 8 / Self::CHUNK_SIZE * Self::CHUNK_SIZE;
118+
let mut byte_offset = Self::chunk_pos(bit_offset) * Self::CHUNK_SIZE;
114119
let pruned_bytes = self.pruned_bytes();
115120
assert!(byte_offset >= pruned_bytes, "bit pruned");
116121
byte_offset -= pruned_bytes;
@@ -145,26 +150,26 @@ impl<H: CHasher> Bitmap<H> {
145150
"cannot add byte when not byte aligned"
146151
);
147152

148-
let chunk_byte = self.next_bit / 8;
153+
let chunk_byte = (self.next_bit / 8) as usize;
149154
self.last_chunk_mut()[chunk_byte] = byte;
150155
self.next_bit += 8;
151-
assert!(self.next_bit <= Self::CHUNK_SIZE * 8);
156+
assert!(self.next_bit <= Self::CHUNK_SIZE_BITS);
152157

153-
if self.next_bit == Self::CHUNK_SIZE * 8 {
158+
if self.next_bit == Self::CHUNK_SIZE_BITS {
154159
self.commit_last_chunk(hasher);
155160
}
156161
}
157162

158163
/// Add a single bit to the bitmap.
159164
pub fn append(&mut self, hasher: &mut H, bit: bool) {
160165
if bit {
161-
let chunk_byte = self.next_bit / 8;
162-
self.last_chunk_mut()[chunk_byte] |= Self::chunk_byte_bit_mask(self.next_bit as u64);
166+
let chunk_byte = (self.next_bit / 8) as usize;
167+
self.last_chunk_mut()[chunk_byte] |= Self::chunk_byte_bit_mask(self.next_bit);
163168
}
164169
self.next_bit += 1;
165-
assert!(self.next_bit <= Self::CHUNK_SIZE * 8);
170+
assert!(self.next_bit <= Self::CHUNK_SIZE_BITS);
166171

167-
if self.next_bit == Self::CHUNK_SIZE * 8 {
172+
if self.next_bit == Self::CHUNK_SIZE_BITS {
168173
self.commit_last_chunk(hasher);
169174
}
170175
}
@@ -179,21 +184,25 @@ impl<H: CHasher> Bitmap<H> {
179184
#[allow(dead_code)] // Remove when we start using this outside the test module.
180185
#[inline]
181186
pub(crate) fn chunk_byte_offset(bit_offset: u64) -> usize {
182-
(bit_offset as usize / 8) % Self::CHUNK_SIZE
187+
(bit_offset / 8) as usize % Self::CHUNK_SIZE
183188
}
184189

185190
/// Convert a bit offset into the position of the Merkle tree leaf it belongs to.
186191
#[inline]
187192
pub(crate) fn leaf_pos(bit_offset: u64) -> u64 {
188-
let leaf_num = bit_offset / 8 / Self::CHUNK_SIZE as u64;
189-
leaf_num_to_pos(leaf_num)
193+
leaf_num_to_pos(Self::chunk_pos(bit_offset) as u64)
194+
}
195+
196+
// Convert a bit offset into the position of the chunk it belongs to.
197+
#[inline]
198+
fn chunk_pos(bit_offset: u64) -> usize {
199+
(bit_offset / 8) as usize / Self::CHUNK_SIZE
190200
}
191201

192202
/// Get the value of a bit. Panics if the bit doesn't exist or has been pruned.
193203
pub fn get_bit(&self, bit_offset: u64) -> bool {
194204
assert!(bit_offset < self.bit_count(), "out of bounds");
195-
let chunk_pos = bit_offset / 8 / Self::CHUNK_SIZE as u64;
196-
if chunk_pos < self.mmr.oldest_retained_pos {
205+
if Self::chunk_pos(bit_offset) < self.mmr.oldest_retained_pos as usize {
197206
panic!("bit pruned");
198207
}
199208
let byte_offset = bit_offset as usize / 8 - self.pruned_bytes();
@@ -203,8 +212,7 @@ impl<H: CHasher> Bitmap<H> {
203212
/// Set the value of the referenced bit. Panics if the bit doesn't exist or has been pruned.
204213
pub fn set_bit(&mut self, hasher: &mut H, bit_offset: u64, bit: bool) {
205214
assert!(bit_offset < self.bit_count(), "out of bounds");
206-
let chunk_pos = bit_offset / 8 / Self::CHUNK_SIZE as u64;
207-
if chunk_pos < self.mmr.oldest_retained_pos {
215+
if Self::chunk_pos(bit_offset) < self.mmr.oldest_retained_pos as usize {
208216
panic!("bit pruned");
209217
}
210218

0 commit comments

Comments
 (0)