solana_sdk/
shred_version.rs1#![cfg(feature = "full")]
6
7use solana_sdk::{
8 hard_forks::HardForks,
9 hash::{extend_and_hash, Hash},
10};
11
12pub fn version_from_hash(hash: &Hash) -> u16 {
13 let hash = hash.as_ref();
14 let mut accum = [0u8; 2];
15 hash.chunks(2).for_each(|seed| {
16 accum
17 .iter_mut()
18 .zip(seed)
19 .for_each(|(accum, seed)| *accum ^= *seed)
20 });
21 #[allow(clippy::arithmetic_side_effects)]
24 let version = ((accum[0] as u16) << 8) | accum[1] as u16;
25
26 version.saturating_add(1)
28}
29
30pub fn compute_shred_version(genesis_hash: &Hash, hard_forks: Option<&HardForks>) -> u16 {
31 use byteorder::{ByteOrder, LittleEndian};
32
33 let mut hash = *genesis_hash;
34 if let Some(hard_forks) = hard_forks {
35 for (slot, count) in hard_forks.iter() {
36 let mut buf = [0u8; 16];
37 LittleEndian::write_u64(&mut buf[..8], *slot);
38 LittleEndian::write_u64(&mut buf[8..], *count as u64);
39 hash = extend_and_hash(&hash, &buf);
40 }
41 }
42
43 version_from_hash(&hash)
44}
45
46#[cfg(test)]
47mod tests {
48 use super::*;
49
50 #[test]
51 fn test_compute_shred_version() {
52 assert_eq!(compute_shred_version(&Hash::default(), None), 1);
53 let mut hard_forks = HardForks::default();
54 assert_eq!(
55 compute_shred_version(&Hash::default(), Some(&hard_forks)),
56 1
57 );
58 hard_forks.register(1);
59 assert_eq!(
60 compute_shred_version(&Hash::default(), Some(&hard_forks)),
61 55551
62 );
63 hard_forks.register(1);
64 assert_eq!(
65 compute_shred_version(&Hash::default(), Some(&hard_forks)),
66 46353
67 );
68 }
69}