1use alloc::{collections::BTreeSet, vec::Vec};
2
3use crate::{
4 bytesrepr::{self, Bytes, FromBytes, ToBytes},
5 PublicKey,
6};
7
8#[cfg(feature = "datasize")]
9use datasize::DataSize;
10#[cfg(feature = "json-schema")]
11use schemars::JsonSchema;
12
13use serde::{Deserialize, Serialize};
14use tracing::error;
15
16#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Default, Serialize, Deserialize)]
21#[cfg_attr(feature = "datasize", derive(DataSize))]
22#[cfg_attr(feature = "json-schema", derive(JsonSchema))]
23pub struct RewardedSignatures(Vec<SingleBlockRewardedSignatures>);
24
25#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Default, Serialize, Deserialize)]
33#[cfg_attr(feature = "datasize", derive(DataSize))]
34#[cfg_attr(feature = "json-schema", derive(JsonSchema))]
35pub struct SingleBlockRewardedSignatures(Vec<u8>);
36
37impl SingleBlockRewardedSignatures {
38 pub fn from_validator_set<'a>(
41 public_keys: &BTreeSet<PublicKey>,
42 all_validators: impl IntoIterator<Item = &'a PublicKey>,
43 ) -> Self {
44 let result = Self::pack(
48 all_validators
49 .into_iter()
50 .map(|key| u8::from(public_keys.contains(key))),
51 );
52
53 let included_count: u32 = result.0.iter().map(|c| c.count_ones()).sum();
54 if included_count as usize != public_keys.len() {
55 error!(
56 included_count,
57 expected_count = public_keys.len(),
58 "error creating past finality signatures from validator set"
59 );
60 }
61
62 result
63 }
64
65 pub fn to_validator_set(
68 &self,
69 all_validators: impl IntoIterator<Item = PublicKey>,
70 ) -> BTreeSet<PublicKey> {
71 self.unpack()
72 .zip(all_validators)
73 .filter_map(|(active, validator)| (active != 0).then_some(validator))
74 .collect()
75 }
76
77 #[doc(hidden)]
82 pub fn pack(bits: impl Iterator<Item = u8>) -> Self {
83 fn set_bit_at(value: u8, position: usize) -> u8 {
86 let value = u8::from(value != 0);
88
89 value << (7 - position)
90 }
91
92 let inner = chunks_8(bits)
93 .map(|bits_chunk| {
94 bits_chunk
95 .enumerate()
96 .fold(0, |acc, (pos, value)| acc | set_bit_at(value, pos))
97 })
98 .collect();
99
100 SingleBlockRewardedSignatures(inner)
101 }
102
103 #[doc(hidden)]
106 pub fn unpack(&self) -> impl Iterator<Item = u8> + '_ {
107 fn bit_at(byte: u8, position: u8) -> u8 {
109 (byte & (0b1000_0000 >> position)) >> (7 - position)
110 }
111
112 self.0
113 .iter()
114 .flat_map(|&byte| (0..8).map(move |i| bit_at(byte, i)))
115 }
116
117 #[doc(hidden)]
119 pub fn difference(mut self, other: &SingleBlockRewardedSignatures) -> Self {
120 for (self_byte, other_byte) in self.0.iter_mut().zip(other.0.iter()) {
121 *self_byte &= !other_byte;
122 }
123 self
124 }
125
126 pub fn intersection(mut self, other: &SingleBlockRewardedSignatures) -> Self {
128 self.0 = self
129 .0
130 .iter()
131 .zip(other.0.iter())
132 .map(|(a, b)| *a & *b)
133 .collect();
134 self
135 }
136
137 pub fn has_some(&self) -> bool {
139 self.0.iter().any(|byte| *byte != 0)
140 }
141}
142
143impl ToBytes for SingleBlockRewardedSignatures {
144 fn to_bytes(&self) -> Result<Vec<u8>, bytesrepr::Error> {
145 let mut buffer = bytesrepr::allocate_buffer(self)?;
146 buffer.extend(Bytes::from(self.0.as_ref()).to_bytes()?);
147 Ok(buffer)
148 }
149
150 fn serialized_length(&self) -> usize {
151 self.0.serialized_length()
152 }
153}
154
155impl FromBytes for SingleBlockRewardedSignatures {
156 fn from_bytes(bytes: &[u8]) -> Result<(Self, &[u8]), bytesrepr::Error> {
157 let (inner, rest) = Bytes::from_bytes(bytes)?;
158 Ok((SingleBlockRewardedSignatures(inner.into()), rest))
159 }
160}
161
162impl RewardedSignatures {
163 pub fn new<I: IntoIterator<Item = SingleBlockRewardedSignatures>>(
165 single_block_signatures: I,
166 ) -> Self {
167 Self(single_block_signatures.into_iter().collect())
168 }
169
170 pub fn pack(unpacked: Vec<Vec<u8>>) -> Self {
173 Self(
174 unpacked
175 .into_iter()
176 .map(|single_block_signatures| {
177 SingleBlockRewardedSignatures::pack(single_block_signatures.into_iter())
178 })
179 .collect(),
180 )
181 }
182
183 pub fn unpack(&self) -> Vec<Vec<u8>> {
186 self.0
187 .iter()
188 .map(|single_block_signatures| single_block_signatures.unpack().collect())
189 .collect()
190 }
191
192 pub fn left_padded(self, num_blocks: usize) -> Self {
195 Self(
196 core::iter::repeat_with(SingleBlockRewardedSignatures::default)
197 .take(num_blocks)
198 .chain(self.0)
199 .collect(),
200 )
201 }
202
203 pub fn difference(self, other: &RewardedSignatures) -> Self {
205 Self(
206 self.0
207 .into_iter()
208 .zip(other.0.iter())
209 .map(|(single_block_signatures, other_block_signatures)| {
210 single_block_signatures.difference(other_block_signatures)
211 })
212 .collect(),
213 )
214 }
215
216 pub fn intersection(&self, other: &RewardedSignatures) -> Self {
218 Self(
219 self.0
220 .iter()
221 .zip(other.0.iter())
222 .map(|(single_block_signatures, other_block_signatures)| {
223 single_block_signatures
224 .clone()
225 .intersection(other_block_signatures)
226 })
227 .collect(),
228 )
229 }
230
231 pub fn iter(&self) -> impl Iterator<Item = &SingleBlockRewardedSignatures> {
233 self.0.iter()
234 }
235
236 pub fn iter_with_height(
240 &self,
241 block_height: u64,
242 ) -> impl Iterator<Item = (u64, &SingleBlockRewardedSignatures)> {
243 self.0.iter().enumerate().map(move |(rel_height, sbrs)| {
244 (
245 block_height
246 .saturating_sub(rel_height as u64)
247 .saturating_sub(1),
248 sbrs,
249 )
250 })
251 }
252
253 pub fn has_some(&self) -> bool {
255 self.0.iter().any(|signatures| signatures.has_some())
256 }
257}
258
259pub(crate) static EMPTY: RewardedSignatures = RewardedSignatures(Vec::new());
260
261impl ToBytes for RewardedSignatures {
262 fn to_bytes(&self) -> Result<Vec<u8>, bytesrepr::Error> {
263 self.0.to_bytes()
264 }
265
266 fn serialized_length(&self) -> usize {
267 self.0.serialized_length()
268 }
269}
270
271impl FromBytes for RewardedSignatures {
272 fn from_bytes(bytes: &[u8]) -> Result<(Self, &[u8]), bytesrepr::Error> {
273 Vec::<SingleBlockRewardedSignatures>::from_bytes(bytes)
274 .map(|(inner, rest)| (RewardedSignatures(inner), rest))
275 }
276}
277
278fn chunks_8(bits: impl Iterator<Item = u8>) -> impl Iterator<Item = impl Iterator<Item = u8>> {
280 struct Chunks<B>(B);
281
282 struct Chunk {
283 values: [u8; 8],
284 index: usize,
285 max: usize,
286 }
287
288 impl<B> Iterator for Chunks<B>
289 where
290 B: Iterator<Item = u8>,
291 {
292 type Item = Chunk;
293
294 fn next(&mut self) -> Option<Self::Item> {
295 let mut values = [0; 8];
296 let max = core::iter::zip(&mut values, &mut self.0)
297 .map(|(array_slot, value)| *array_slot = value)
298 .count();
299
300 (max != 0).then_some(Chunk {
301 values,
302 max,
303 index: 0,
304 })
305 }
306 }
307
308 impl Iterator for Chunk {
309 type Item = u8;
310
311 fn next(&mut self) -> Option<Self::Item> {
312 if self.index < self.max {
313 let n = self.values.get(self.index).cloned();
314 self.index += 1;
315 n
316 } else {
317 None
318 }
319 }
320 }
321
322 Chunks(bits)
323}
324
325#[cfg(any(feature = "testing", test))]
326impl SingleBlockRewardedSignatures {
327 pub fn random(rng: &mut crate::testing::TestRng, n_validators: usize) -> Self {
329 let mut bytes = vec![0; (n_validators + 7) / 8];
330
331 rand::RngCore::fill_bytes(rng, bytes.as_mut());
332
333 SingleBlockRewardedSignatures(bytes)
334 }
335}
336
337#[cfg(test)]
338mod tests {
339 use super::{chunks_8, SingleBlockRewardedSignatures};
340 use crate::{
341 bytesrepr::{FromBytes, ToBytes},
342 testing::TestRng,
343 PublicKey,
344 };
345 use rand::{seq::IteratorRandom, Rng};
346 use std::collections::BTreeSet;
347
348 #[test]
349 fn empty_signatures() {
350 let rng = &mut TestRng::new();
351 let validators: Vec<_> = std::iter::repeat_with(|| PublicKey::random(rng))
352 .take(7)
353 .collect();
354 let original_signed = BTreeSet::new();
355
356 let past_finality_signatures =
357 SingleBlockRewardedSignatures::from_validator_set(&original_signed, validators.iter());
358
359 assert_eq!(past_finality_signatures.0, &[0]);
360
361 let signed = past_finality_signatures.to_validator_set(validators);
362
363 assert_eq!(original_signed, signed);
364 }
365
366 #[test]
367 fn from_and_to_methods_match_in_a_simple_case() {
368 let rng = &mut TestRng::new();
369 let validators: Vec<_> = std::iter::repeat_with(|| PublicKey::random(rng))
370 .take(11)
371 .collect();
372 let signed = {
373 let mut signed = BTreeSet::new();
374 signed.insert(validators[2].clone());
375 signed.insert(validators[5].clone());
376 signed.insert(validators[6].clone());
377 signed.insert(validators[8].clone());
378 signed.insert(validators[10].clone());
379 signed
380 };
381
382 let past_finality_signatures =
383 SingleBlockRewardedSignatures::from_validator_set(&signed, validators.iter());
384
385 assert_eq!(past_finality_signatures.0, &[0b0010_0110, 0b1010_0000]);
386
387 let signed_ = past_finality_signatures.to_validator_set(validators);
388
389 assert_eq!(signed, signed_);
390 }
391
392 #[test]
393 fn simple_serialization_roundtrip() {
394 let data = SingleBlockRewardedSignatures(vec![1, 2, 3, 4, 5]);
395
396 let serialized = data.to_bytes().unwrap();
397 assert_eq!(serialized.len(), data.0.len() + 4);
398 assert_eq!(data.serialized_length(), data.0.len() + 4);
399
400 let (deserialized, rest) = SingleBlockRewardedSignatures::from_bytes(&serialized).unwrap();
401
402 assert_eq!(data, deserialized);
403 assert_eq!(rest, &[0u8; 0]);
404 }
405
406 #[test]
407 fn serialization_roundtrip_of_empty_data() {
408 let data = SingleBlockRewardedSignatures::default();
409
410 let serialized = data.to_bytes().unwrap();
411 assert_eq!(serialized, &[0; 4]);
412 assert_eq!(data.serialized_length(), 4);
413
414 let (deserialized, rest) = SingleBlockRewardedSignatures::from_bytes(&serialized).unwrap();
415
416 assert_eq!(data, deserialized);
417 assert_eq!(rest, &[0u8; 0]);
418 }
419
420 #[test]
421 fn serialization_roundtrip_of_random_data() {
422 let rng = &mut TestRng::new();
423 let n_validators = rng.gen_range(50..200);
424 let all_validators: BTreeSet<_> = std::iter::repeat_with(|| PublicKey::random(rng))
425 .take(n_validators)
426 .collect();
427 let n_to_sign = rng.gen_range(0..all_validators.len());
428 let public_keys = all_validators
429 .iter()
430 .cloned()
431 .choose_multiple(rng, n_to_sign)
432 .into_iter()
433 .collect();
434
435 let past_finality_signatures =
436 SingleBlockRewardedSignatures::from_validator_set(&public_keys, all_validators.iter());
437
438 let serialized = past_finality_signatures.to_bytes().unwrap();
439 let (deserialized, rest) = SingleBlockRewardedSignatures::from_bytes(&serialized).unwrap();
440
441 assert_eq!(public_keys, deserialized.to_validator_set(all_validators));
442 assert_eq!(rest, &[0u8; 0]);
443 }
444
445 #[test]
446 fn chunk_iterator() {
447 fn v(maybe_chunk: Option<impl Iterator<Item = u8>>) -> Option<Vec<u8>> {
448 maybe_chunk.map(itertools::Itertools::collect_vec)
449 }
450
451 let mut chunks = chunks_8(IntoIterator::into_iter([]));
454
455 assert_eq!(v(chunks.next()), None);
456
457 let mut chunks = chunks_8(IntoIterator::into_iter([10, 11, 12, 13, 14, 15, 16, 17]));
460
461 assert_eq!(v(chunks.next()), Some(vec![10, 11, 12, 13, 14, 15, 16, 17]));
462 assert_eq!(v(chunks.next()), None);
463
464 let mut chunks = chunks_8(IntoIterator::into_iter([
467 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26,
468 ]));
469
470 assert_eq!(v(chunks.next()), Some(vec![10, 11, 12, 13, 14, 15, 16, 17]));
471 assert_eq!(v(chunks.next()), Some(vec![18, 19, 20, 21, 22, 23, 24, 25]));
472 assert_eq!(v(chunks.next()), Some(vec![26]));
473 }
474}