commonware_utils/
lib.rs

1//! Leverage common functionality across multiple primitives.
2
3use prost::{encode_length_delimiter, length_delimiter_len};
4
5pub mod array;
6pub use array::Array;
7mod time;
8pub use time::SystemTimeExt;
9mod priority_set;
10pub use priority_set::PrioritySet;
11pub mod futures;
12
13/// Converts bytes to a hexadecimal string.
14pub fn hex(bytes: &[u8]) -> String {
15    let mut hex = String::new();
16    for byte in bytes.iter() {
17        hex.push_str(&format!("{:02x}", byte));
18    }
19    hex
20}
21
22/// Converts a hexadecimal string to bytes.
23pub fn from_hex(hex: &str) -> Option<Vec<u8>> {
24    if hex.len() % 2 != 0 {
25        return None;
26    }
27
28    (0..hex.len())
29        .step_by(2)
30        .map(|i| match u8::from_str_radix(&hex[i..i + 2], 16) {
31            Ok(byte) => Some(byte),
32            Err(_) => None,
33        })
34        .collect()
35}
36
37/// Converts a hexadecimal string to bytes, stripping whitespace and/or a `0x` prefix. Commonly used
38/// in testing to encode external test vectors without modification.
39pub fn from_hex_formatted(hex: &str) -> Option<Vec<u8>> {
40    let hex = hex.replace(['\t', '\n', '\r', ' '], "");
41    let res = hex.strip_prefix("0x").unwrap_or(&hex);
42    from_hex(res)
43}
44
45/// Compute the maximum value of `f` (faults) that can be tolerated given `n = 3f + 1`.
46pub fn max_faults(n: u32) -> Option<u32> {
47    let f = n.checked_sub(1)? / 3;
48    if f == 0 {
49        return None;
50    }
51    Some(f)
52}
53
54/// Assuming that `n = 3f + 1`, compute the minimum size of `q` such that `q >= 2f + 1`.
55///
56/// If the value of `n` is too small to tolerate any faults, this function returns `None`.
57pub fn quorum(n: u32) -> Option<u32> {
58    let f = max_faults(n)?;
59    Some((2 * f) + 1)
60}
61
62/// Computes the union of two byte slices.
63pub fn union(a: &[u8], b: &[u8]) -> Vec<u8> {
64    let mut union = Vec::with_capacity(a.len() + b.len());
65    union.extend_from_slice(a);
66    union.extend_from_slice(b);
67    union
68}
69
70/// Concatenate a namespace and a message, prepended by a varint encoding of the namespace length.
71///
72/// This produces a unique byte sequence (i.e. no collisions) for each `(namespace, msg)` pair.
73pub fn union_unique(namespace: &[u8], msg: &[u8]) -> Vec<u8> {
74    let ld_len = length_delimiter_len(namespace.len());
75    let mut result = Vec::with_capacity(ld_len + namespace.len() + msg.len());
76    encode_length_delimiter(namespace.len(), &mut result).unwrap();
77    result.extend_from_slice(namespace);
78    result.extend_from_slice(msg);
79    result
80}
81
82/// Compute the modulo of bytes interpreted as a big-endian integer.
83///
84/// This function is used to select a random entry from an array
85/// when the bytes are a random seed.
86pub fn modulo(bytes: &[u8], n: u64) -> u64 {
87    let mut result = 0;
88    for &byte in bytes {
89        result = (result << 8) | (byte as u64);
90        result %= n;
91    }
92    result
93}
94
95/// Types with a constant encoded length.
96pub trait SizedSerialize {
97    const SERIALIZED_LEN: usize;
98}
99
100impl SizedSerialize for u8 {
101    const SERIALIZED_LEN: usize = 1;
102}
103
104impl SizedSerialize for u16 {
105    const SERIALIZED_LEN: usize = 2;
106}
107
108impl SizedSerialize for u32 {
109    const SERIALIZED_LEN: usize = 4;
110}
111
112impl SizedSerialize for u64 {
113    const SERIALIZED_LEN: usize = 8;
114}
115
116impl SizedSerialize for u128 {
117    const SERIALIZED_LEN: usize = 16;
118}
119
120#[cfg(test)]
121mod tests {
122    use super::*;
123    use num_bigint::BigUint;
124    use rand::{rngs::StdRng, Rng, SeedableRng};
125
126    #[test]
127    fn test_hex() {
128        // Test case 0: empty bytes
129        let b = &[];
130        let h = hex(b);
131        assert_eq!(h, "");
132        assert_eq!(from_hex(&h).unwrap(), b.to_vec());
133
134        // Test case 1: single byte
135        let b = &[0x01];
136        let h = hex(b);
137        assert_eq!(h, "01");
138        assert_eq!(from_hex(&h).unwrap(), b.to_vec());
139
140        // Test case 2: multiple bytes
141        let b = &[0x01, 0x02, 0x03];
142        let h = hex(b);
143        assert_eq!(h, "010203");
144        assert_eq!(from_hex(&h).unwrap(), b.to_vec());
145
146        // Test case 3: odd number of bytes
147        let h = "0102030";
148        assert!(from_hex(h).is_none());
149
150        // Test case 4: invalid hexadecimal character
151        let h = "01g3";
152        assert!(from_hex(h).is_none());
153    }
154
155    #[test]
156    fn test_from_hex_formatted() {
157        // Test case 0: empty bytes
158        let b = &[];
159        let h = hex(b);
160        assert_eq!(h, "");
161        assert_eq!(from_hex_formatted(&h).unwrap(), b.to_vec());
162
163        // Test case 1: single byte
164        let b = &[0x01];
165        let h = hex(b);
166        assert_eq!(h, "01");
167        assert_eq!(from_hex_formatted(&h).unwrap(), b.to_vec());
168
169        // Test case 2: multiple bytes
170        let b = &[0x01, 0x02, 0x03];
171        let h = hex(b);
172        assert_eq!(h, "010203");
173        assert_eq!(from_hex_formatted(&h).unwrap(), b.to_vec());
174
175        // Test case 3: odd number of bytes
176        let h = "0102030";
177        assert!(from_hex_formatted(h).is_none());
178
179        // Test case 4: invalid hexadecimal character
180        let h = "01g3";
181        assert!(from_hex_formatted(h).is_none());
182
183        // Test case 5: whitespace
184        let h = "01 02 03";
185        assert_eq!(from_hex_formatted(h).unwrap(), b.to_vec());
186
187        // Test case 6: 0x prefix
188        let h = "0x010203";
189        assert_eq!(from_hex_formatted(h).unwrap(), b.to_vec());
190
191        // Test case 7: 0x prefix + different whitespace chars
192        let h = "    \n\n0x\r\n01
193                            02\t03\n";
194        assert_eq!(from_hex_formatted(h).unwrap(), b.to_vec());
195    }
196
197    #[test]
198    fn test_quorum() {
199        // Test case 0: n = 3 (3*0 + 1)
200        assert_eq!(quorum(3), None);
201
202        // Test case 1: n = 4 (3*1 + 1)
203        assert_eq!(quorum(4), Some(3));
204
205        // Test case 2: n = 7 (3*2 + 1)
206        assert_eq!(quorum(7), Some(5));
207
208        // Test case 3: n = 10 (3*3 + 1)
209        assert_eq!(quorum(10), Some(7));
210    }
211
212    #[test]
213    fn test_union() {
214        // Test case 0: empty slices
215        assert_eq!(union(&[], &[]), []);
216
217        // Test case 1: empty and non-empty slices
218        assert_eq!(union(&[], &[0x01, 0x02, 0x03]), [0x01, 0x02, 0x03]);
219
220        // Test case 2: non-empty and non-empty slices
221        assert_eq!(
222            union(&[0x01, 0x02, 0x03], &[0x04, 0x05, 0x06]),
223            [0x01, 0x02, 0x03, 0x04, 0x05, 0x06]
224        );
225    }
226
227    #[test]
228    fn test_union_unique() {
229        let namespace = b"namespace";
230        let msg = b"message";
231
232        let length_encoding = vec![0b0000_1001];
233        let mut expected = Vec::with_capacity(length_encoding.len() + namespace.len() + msg.len());
234        expected.extend_from_slice(&length_encoding);
235        expected.extend_from_slice(namespace);
236        expected.extend_from_slice(msg);
237
238        let result = union_unique(namespace, msg);
239        assert_eq!(result, expected);
240        assert_eq!(result.len(), result.capacity());
241    }
242
243    #[test]
244    fn test_union_unique_zero_length() {
245        let namespace = b"";
246        let msg = b"message";
247
248        let length_encoding = vec![0];
249        let mut expected = Vec::with_capacity(length_encoding.len() + namespace.len() + msg.len());
250        expected.extend_from_slice(&length_encoding);
251        expected.extend_from_slice(msg);
252
253        let result = union_unique(namespace, msg);
254        assert_eq!(result, expected);
255        assert_eq!(result.len(), result.capacity());
256    }
257
258    #[test]
259    fn test_union_unique_long_length() {
260        // Use a namespace of over length 127.
261        let namespace = &b"n".repeat(256);
262        let msg = b"message";
263
264        let length_encoding = vec![0b1000_0000, 0b0000_0010];
265        let mut expected = Vec::with_capacity(length_encoding.len() + namespace.len() + msg.len());
266        expected.extend_from_slice(&length_encoding);
267        expected.extend_from_slice(namespace);
268        expected.extend_from_slice(msg);
269
270        let result = union_unique(namespace, msg);
271        assert_eq!(result, expected);
272        assert_eq!(result.len(), result.capacity());
273    }
274
275    #[test]
276    fn test_modulo() {
277        // Test case 0: empty bytes
278        assert_eq!(modulo(&[], 1), 0);
279
280        // Test case 1: single byte
281        assert_eq!(modulo(&[0x01], 1), 0);
282
283        // Test case 2: multiple bytes
284        assert_eq!(modulo(&[0x01, 0x02, 0x03], 10), 1);
285
286        // Test case 3: check equivalence with BigUint
287        let n = 11u64;
288        for i in 0..100 {
289            let mut rng = StdRng::seed_from_u64(i);
290            let bytes: [u8; 32] = rng.gen();
291            let big_modulo = BigUint::from_bytes_be(&bytes) % n;
292            let utils_modulo = modulo(&bytes, n);
293            assert_eq!(big_modulo, BigUint::from(utils_modulo));
294        }
295    }
296}