hooks_rs/api/
util.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
use core::mem::MaybeUninit;

use crate::c;

use super::*;

/// Convert a 20 byte Account ID to an r-address of 25 and 35 characters in length.
///
/// The resulting buffer might not be fully populated because size of an r-address varies.
/// The rest of the buffer will be filled with zeroes.
#[inline(always)]
pub fn util_raddr(accid: &[u8; 20]) -> Result<[u8; 35]> {
    let mut uninit_r_address_buffer: [MaybeUninit<u8>; 35] = MaybeUninit::uninit_array();

    let u64_uninit_r_address_buffer_ptr = uninit_r_address_buffer.as_mut_ptr() as *mut u64;
    unsafe {
        u64_uninit_r_address_buffer_ptr.write(0); // 8 bytes
        u64_uninit_r_address_buffer_ptr.add(1).write(0); // 16 bytes
        u64_uninit_r_address_buffer_ptr.add(2).write(0); // 24 bytes
        u64_uninit_r_address_buffer_ptr.add(3).write(0); // 32 bytes
    }
    unsafe {
        let r_address_last_3_bytes_ptr = uninit_r_address_buffer.get_unchecked_mut(32).as_mut_ptr();
        r_address_last_3_bytes_ptr.write(0);
        r_address_last_3_bytes_ptr.add(1).write(0);
        r_address_last_3_bytes_ptr.add(2).write(0);
    };
    let mut r_address_buffer = unsafe {
        uninit_r_address_buffer
            .as_ptr()
            .cast::<[u8; 35]>()
            .read_volatile()
    };

    let result: Result<u64> = unsafe {
        c::util_raddr(
            r_address_buffer.as_mut_ptr() as u32,
            35,
            accid.as_ptr() as u32,
            ACC_ID_LEN as u32,
        )
        .into()
    };

    match result {
        Ok(_) => Ok(r_address_buffer),
        Err(e) => Err(e),
    }
}

/// Convert an r-address into a 20 byte Account ID
///
/// R_ADDRESS_LEN must be >= 25 && <= 35.
#[inline(always)]
pub fn util_accid<const R_ADDRESS_LEN: usize>(raddr_in: &[u8; R_ADDRESS_LEN]) -> Result<[u8; 20]> {
    let func = |buffer_mut_ptr: *mut MaybeUninit<u8>| {
        let result: Result<u64> = unsafe {
            c::util_raddr(
                buffer_mut_ptr as u32,
                ACC_ID_LEN as u32,
                raddr_in.as_ptr() as u32,
                R_ADDRESS_LEN as u32,
            )
            .into()
        };

        result
    };

    init_buffer_mut::<ACC_ID_LEN, _>(func)
}

/// Verify a cryptographic signature
///
/// If the public key is prefixed with 0xED then use ED25519. Otherwise assume SECP256k1.
#[inline(always)]
pub fn util_verify(payload: &[u8], signature: &[u8], publickey: &[u8]) -> Result<bool> {
    let result: Result<u64> = unsafe {
        c::util_verify(
            payload.as_ptr() as _,
            payload.len() as _,
            signature.as_ptr() as _,
            signature.len() as _,
            publickey.as_ptr() as _,
            publickey.len() as _,
        )
        .into()
    };

    match result {
        Ok(0) => Ok(false),
        Ok(1) => Ok(true),
        Err(e) => Err(e),
        _ => unreachable!(),
    }
}

/// Compute an sha512-half over some data
#[inline(always)]
pub fn util_sha512h(data_in: &[u8]) -> Result<[u8; HASH_LEN]> {
    let func = |buffer_mut_ptr: *mut MaybeUninit<u8>| {
        let result: Result<u64> = unsafe {
            c::util_sha512h(
                buffer_mut_ptr as u32,
                HASH_LEN as u32,
                data_in.as_ptr() as u32,
                data_in.len() as u32,
            )
            .into()
        };

        result
    };

    init_buffer_mut(func)
}