Skip to content

Commit 1ef94fe

Browse files
committed
switch gossip to bitvec crate for better low-level API
1 parent e033ccc commit 1ef94fe

File tree

6 files changed

+120
-19
lines changed

6 files changed

+120
-19
lines changed

Cargo.lock

+2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -291,6 +291,7 @@ backoff = "0.4.0"
291291
base64 = "0.22.1"
292292
bincode = "1.3.3"
293293
bitflags = { version = "2.8.0" }
294+
bitvec = "1.0.1"
294295
blake3 = "1.5.5"
295296
borsh = { version = "1.5.5", features = ["derive", "unstable__schema"] }
296297
borsh0-10 = { package = "borsh", version = "0.10.3" }

gossip/Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ edition = { workspace = true }
1212
[dependencies]
1313
assert_matches = { workspace = true }
1414
bincode = { workspace = true }
15+
bitvec = { workspace = true, features = ["serde"] }
1516
bv = { workspace = true, features = ["serde"] }
1617
clap = { workspace = true }
1718
crossbeam-channel = { workspace = true }

gossip/src/epoch_slots.rs

+34-19
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use {
44
protocol::MAX_CRDS_OBJECT_SIZE,
55
},
66
bincode::serialized_size,
7-
bv::BitVec,
7+
bitvec::prelude::BitVec,
88
flate2::{Compress, Compression, Decompress, FlushCompress, FlushDecompress},
99
solana_sanitize::{Sanitize, SanitizeError},
1010
solana_sdk::{clock::Slot, pubkey::Pubkey},
@@ -81,30 +81,44 @@ impl std::convert::From<flate2::DecompressError> for Error {
8181
}
8282

8383
impl Flate2 {
84-
fn deflate(mut unc: Uncompressed) -> Result<Self> {
85-
let mut compressed = Vec::with_capacity(unc.slots.block_capacity());
84+
fn deflate(unc: Uncompressed) -> Result<Self> {
85+
// View into the slots array as raw bytes
86+
let bits = unc.slots.as_raw_slice();
87+
// Assume compressed version will be smaller than the original
88+
let mut compressed = Vec::with_capacity(bits.len());
89+
// Perform compression and check status to make sure everything fits
8690
let mut compressor = Compress::new(Compression::best(), false);
87-
let first_slot = unc.first_slot;
88-
let num = unc.num;
89-
unc.slots.shrink_to_fit();
90-
let bits = unc.slots.into_boxed_slice();
91-
compressor.compress_vec(&bits, &mut compressed, FlushCompress::Finish)?;
91+
let status = compressor.compress_vec(bits, &mut compressed, FlushCompress::Finish)?;
92+
if status != flate2::Status::StreamEnd {
93+
return Err(Error::CompressError);
94+
}
95+
9296
let rv = Self {
93-
first_slot,
94-
num,
97+
first_slot: unc.first_slot,
98+
num: unc.num,
9599
compressed,
96100
};
97101
Ok(rv)
98102
}
103+
99104
pub fn inflate(&self) -> Result<Uncompressed> {
100105
//add some head room for the decompressor which might spill more bits
101106
let mut uncompressed = Vec::with_capacity(32 + (self.num + 4) / 8);
107+
// Perform the actual decompression and check that the result fits into provided buffer
102108
let mut decompress = Decompress::new(false);
103-
decompress.decompress_vec(&self.compressed, &mut uncompressed, FlushDecompress::Finish)?;
109+
let status = decompress.decompress_vec(
110+
&self.compressed,
111+
&mut uncompressed,
112+
FlushDecompress::Finish,
113+
)?;
114+
if status != flate2::Status::StreamEnd {
115+
return Err(Error::DecompressError);
116+
}
117+
104118
Ok(Uncompressed {
105119
first_slot: self.first_slot,
106120
num: self.num,
107-
slots: BitVec::from_bits(&uncompressed),
121+
slots: BitVec::from_vec(uncompressed),
108122
})
109123
}
110124
}
@@ -114,7 +128,7 @@ impl Uncompressed {
114128
Self {
115129
num: 0,
116130
first_slot: 0,
117-
slots: BitVec::new_fill(false, 8 * max_size as u64),
131+
slots: BitVec::repeat(false, 8 * max_size),
118132
}
119133
}
120134
pub fn to_slots(&self, min_slot: Slot) -> Vec<Slot> {
@@ -125,10 +139,10 @@ impl Uncompressed {
125139
(min_slot - self.first_slot) as usize
126140
};
127141
for i in start..self.num {
128-
if i >= self.slots.len() as usize {
142+
if i >= self.slots.len() {
129143
break;
130144
}
131-
if self.slots.get(i as u64) {
145+
if *self.slots.get(i).expect("slot index should be in bounds") {
132146
rv.push(self.first_slot + i as Slot);
133147
}
134148
}
@@ -145,11 +159,12 @@ impl Uncompressed {
145159
if *s < self.first_slot {
146160
return i;
147161
}
148-
if *s - self.first_slot >= self.slots.len() {
162+
let offset = (*s - self.first_slot) as usize;
163+
if offset >= self.slots.len() {
149164
return i;
150165
}
151-
self.slots.set(*s - self.first_slot, true);
152-
self.num = std::cmp::max(self.num, 1 + (*s - self.first_slot) as usize);
166+
self.slots.set(offset, true);
167+
self.num = std::cmp::max(self.num, 1 + offset);
153168
}
154169
slots.len()
155170
}
@@ -422,7 +437,7 @@ mod tests {
422437
assert_eq!(o.sanitize(), Err(SanitizeError::ValueOutOfBounds));
423438

424439
let mut o = slots.clone();
425-
o.slots = BitVec::new_fill(false, 7); // Length not a multiple of 8
440+
o.slots = BitVec::repeat(false, 7); // Length not a multiple of 8
426441
assert_eq!(o.sanitize(), Err(SanitizeError::ValueOutOfBounds));
427442

428443
let mut o = slots.clone();

programs/sbf/Cargo.lock

+41
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

svm/examples/Cargo.lock

+41
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)