commonware_utils/
lib.rs

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