Skip to main content

ctclient_async/
utils.rs

1//! Some utility functions.
2
3pub use openssl::sha::sha256;
4
5#[test]
6fn sha256_test() {
7    assert_eq!(
8        u8_to_hex(&sha256(b"")),
9        "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
10    );
11    assert_eq!(
12        u8_to_hex(&sha256(b"hello")),
13        "2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824"
14    );
15}
16
17/// Convert a hex string with no whitespace or other sepreator into `&[u8]`.
18///
19/// # Example:
20/// ```rust
21/// # use ctclient_async::utils::hex_to_u8;
22/// assert_eq!(&hex_to_u8("aabb"), b"\xaa\xbb");
23/// ```
24pub fn hex_to_u8(hex: &str) -> Vec<u8> {
25    if !hex.len().is_multiple_of(2) {
26        panic!("partial hex?");
27    }
28    let mut vec = Vec::with_capacity(hex.len() / 2);
29    for i in 0..(hex.len() / 2) {
30        let hex = &hex[i * 2..(i + 1) * 2];
31        vec.push(u8::from_str_radix(hex, 16).unwrap());
32    }
33    vec
34}
35
36/// Convert a `&[u8]` byte array to a lower-case, no-sepreator hex string.
37///
38/// # Example:
39/// ```rust
40/// # use ctclient_async::utils::u8_to_hex;
41/// assert_eq!(&u8_to_hex(b"\xaa\xbb"), "aabb");
42/// ```
43pub fn u8_to_hex(bytes: &[u8]) -> String {
44    let mut buf = String::new();
45    for i in bytes {
46        buf.push_str(&format!("{:02x?}", i));
47    }
48    buf
49}
50
51#[test]
52fn hex_to_u8_test() {
53    assert_eq!(hex_to_u8("deadbeef"), vec![0xde, 0xad, 0xbe, 0xef]);
54    assert_eq!(hex_to_u8("DEADBEEF"), vec![0xde, 0xad, 0xbe, 0xef]);
55}
56#[test]
57fn u8_to_hex_test() {
58    assert_eq!(u8_to_hex(&[0xde, 0xad, 0xbe, 0xef]), "deadbeef");
59    assert_eq!(u8_to_hex(&[0x01, 0x02, 0x03, 0x04]), "01020304");
60}
61
62/// Calculate `sha256(0x01 || left || right)`
63pub fn combine_tree_hash(left: &[u8; 32], right: &[u8; 32]) -> [u8; 32] {
64    let mut buf = Vec::with_capacity(32 + 32 + 1);
65    buf.push(1);
66    buf.extend_from_slice(left);
67    buf.extend_from_slice(right);
68    sha256(&buf[..])
69}
70
71/// For a tree of size `n`, return the size of the left branch of the root.
72pub fn largest_power_of_2_smaller_than(mut n: u64) -> u64 {
73    if n <= 1 {
74        return 0;
75    }
76    if n == 2 {
77        return 1;
78    }
79    n -= 1;
80    // I'm sure the compiler can optimize this nicely.
81    let mut pow: u64 = 1;
82    loop {
83        n /= 2;
84        pow *= 2;
85        if n == 1 {
86            return pow;
87        }
88    }
89}
90
91#[test]
92fn test_largest_power_of_2_smaller_than() {
93    assert_eq!(largest_power_of_2_smaller_than(0), 0);
94    assert_eq!(largest_power_of_2_smaller_than(1), 0);
95    assert_eq!(largest_power_of_2_smaller_than(2), 1);
96    assert_eq!(largest_power_of_2_smaller_than(3), 2);
97    assert_eq!(largest_power_of_2_smaller_than(4), 2);
98    assert_eq!(largest_power_of_2_smaller_than(5), 4);
99    assert_eq!(largest_power_of_2_smaller_than(6), 4);
100    assert_eq!(largest_power_of_2_smaller_than(7), 4);
101    assert_eq!(largest_power_of_2_smaller_than(8), 4);
102    assert_eq!(largest_power_of_2_smaller_than(9), 8);
103
104    assert_eq!(
105        largest_power_of_2_smaller_than(1u64 << 33u64),
106        1u64 << 32u64
107    );
108    assert_eq!(
109        largest_power_of_2_smaller_than((1u64 << 34u64) - 100u64),
110        1u64 << 33u64
111    );
112}