Skip to main content

simplicity_sys/
ffi.rs

1// SPDX-License-Identifier: CC0-1.0
2
3//! FFI Bindings
4//!
5//! This module contains bindings to the C library types and functions
6//! that are required to execute jets.
7//! It is split into several modules, each one corresponding to a `.h` file
8//! in the C library.
9//!
10//! All types are converted to CamelCase and prefixed with the letter C;
11//! function names are unchanged.
12
13#![allow(non_camel_case_types)]
14
15pub use core::ffi::c_void;
16
17pub type c_uchar = u8;
18pub type c_int = i32;
19pub type c_uint = u32;
20pub type c_size_t = usize;
21pub type c_uint_fast8_t = u8;
22#[cfg(any(target_os = "macos", target_os = "ios"))]
23pub type c_uint_fast16_t = u16;
24#[cfg(target_os = "windows")]
25pub type c_uint_fast16_t = u32;
26#[cfg(target_arch = "wasm32")]
27pub type c_uint_fast16_t = u16;
28#[cfg(not(any(
29    target_os = "macos",
30    target_os = "ios",
31    target_os = "windows",
32    target_arch = "wasm32"
33)))]
34pub type c_uint_fast16_t = usize;
35
36#[cfg(any(
37    target_os = "macos",
38    target_os = "ios",
39    target_os = "windows",
40    target_arch = "wasm32"
41))]
42pub type c_uint_fast32_t = u32;
43#[cfg(not(any(
44    target_os = "macos",
45    target_os = "ios",
46    target_os = "windows",
47    target_arch = "wasm32"
48)))]
49pub type c_uint_fast32_t = usize;
50#[cfg(target_pointer_width = "64")]
51pub type c_uint_fast64_t = usize;
52#[cfg(not(target_pointer_width = "64"))]
53pub type c_uint_fast64_t = u64;
54pub type c_uint_least32_t = u32;
55
56extern "C" {
57    pub static c_sizeof_uchar: c_size_t;
58    pub static c_alignof_uchar: c_size_t;
59    pub static c_sizeof_int: c_size_t;
60    pub static c_alignof_int: c_size_t;
61    pub static c_sizeof_uint: c_size_t;
62    pub static c_alignof_uint: c_size_t;
63    pub static c_sizeof_size_t: c_size_t;
64    pub static c_alignof_size_t: c_size_t;
65    pub static c_sizeof_uint_fast8_t: c_size_t;
66    pub static c_alignof_uint_fast8_t: c_size_t;
67    pub static c_sizeof_uint_fast16_t: c_size_t;
68    pub static c_alignof_uint_fast16_t: c_size_t;
69    pub static c_sizeof_uint_fast32_t: c_size_t;
70    pub static c_alignof_uint_fast32_t: c_size_t;
71    pub static c_sizeof_uint_fast64_t: c_size_t;
72    pub static c_alignof_uint_fast64_t: c_size_t;
73    pub static c_sizeof_uint_least32_t: c_size_t;
74    pub static c_alignof_uint_least32_t: c_size_t;
75    pub static c_sizeof_long_double: c_size_t;
76    pub static c_alignof_long_double: c_size_t;
77}
78
79pub type ubounded = c_uint_least32_t;
80/// Used with `evalTCOProgram` to enforce consensus limits.
81pub const BUDGET_MAX: ubounded = 4000050;
82/// The max value of UBOUNDED_MAX
83pub const UBOUNDED_MAX: ubounded = ubounded::MAX;
84
85extern "C" {
86    pub static c_sizeof_ubounded: c_size_t;
87    pub static c_alignof_ubounded: c_size_t;
88}
89
90pub mod bounded {
91    use super::ubounded;
92    extern "C" {
93        pub static c_overhead: ubounded;
94    }
95
96    /// constant Overhead of each jet
97    pub fn cost_overhead() -> ubounded {
98        unsafe { c_overhead }
99    }
100}
101
102pub type UWORD = c_uint_fast16_t;
103
104extern "C" {
105    pub static c_sizeof_UWORD: c_size_t;
106    pub static c_alignof_UWORD: c_size_t;
107}
108
109pub mod sha256 {
110    use super::*;
111    use hashes::sha256::Midstate;
112
113    /// The 256-bit array of a SHA-256 hash or midstate.
114    #[repr(C)]
115    #[derive(Copy, Clone, Eq, PartialEq, Debug, Default)]
116    pub struct CSha256Midstate {
117        pub s: [u32; 8],
118    }
119
120    impl From<CSha256Midstate> for Midstate {
121        fn from(c_midstate: CSha256Midstate) -> Midstate {
122            let mut inner = [0; 32];
123            for (idx, chunk) in c_midstate.s.iter().enumerate() {
124                inner[idx * 4..(idx + 1) * 4].copy_from_slice(&chunk.to_be_bytes());
125            }
126            Midstate(inner)
127        }
128    }
129
130    impl From<Midstate> for CSha256Midstate {
131        fn from(midstate: Midstate) -> CSha256Midstate {
132            let mut s = [0; 8];
133            for (idx, chunk) in midstate.0.chunks(4).enumerate() {
134                s[idx] = u32::from_be_bytes([chunk[0], chunk[1], chunk[2], chunk[3]]);
135            }
136            CSha256Midstate { s }
137        }
138    }
139
140    extern "C" {
141        pub static c_sizeof_sha256_midstate: c_size_t;
142        pub static c_alignof_sha256_midstate: c_size_t;
143    }
144}
145
146#[cfg(test)]
147mod tests {
148    use super::*;
149    use std::mem::{align_of, size_of};
150
151    #[test]
152    #[rustfmt::skip]
153    fn test_sizes() {
154        unsafe {
155            assert_eq!(size_of::<c_uchar>(), c_sizeof_uchar);
156            assert_eq!(size_of::<c_int>(), c_sizeof_int);
157            assert_eq!(size_of::<c_uint>(), c_sizeof_uint);
158            assert_eq!(size_of::<c_size_t>(), c_sizeof_size_t);
159            assert_eq!(size_of::<c_uint_fast8_t>(), c_sizeof_uint_fast8_t);
160            assert_eq!(size_of::<c_uint_fast16_t>(), c_sizeof_uint_fast16_t);
161            assert_eq!(size_of::<c_uint_fast32_t>(), c_sizeof_uint_fast32_t);
162            assert_eq!(size_of::<c_uint_fast64_t>(), c_sizeof_uint_fast64_t);
163            assert_eq!(size_of::<c_uint_least32_t>(), c_sizeof_uint_least32_t);
164            assert_eq!(size_of::<ubounded>(), c_sizeof_ubounded);
165            assert_eq!(size_of::<UWORD>(), c_sizeof_UWORD);
166            assert_eq!(size_of::<sha256::CSha256Midstate>(), sha256::c_sizeof_sha256_midstate);
167        }
168    }
169
170    #[test]
171    #[rustfmt::skip]
172    fn test_aligns() {
173        unsafe {
174            assert_eq!(align_of::<c_uchar>(), c_alignof_uchar);
175            assert_eq!(align_of::<c_int>(), c_alignof_int);
176            assert_eq!(align_of::<c_uint>(), c_alignof_uint);
177            assert_eq!(align_of::<c_size_t>(), c_alignof_size_t);
178            assert_eq!(align_of::<c_uint_fast8_t>(), c_alignof_uint_fast8_t);
179            assert_eq!(align_of::<c_uint_fast16_t>(), c_alignof_uint_fast16_t);
180            assert_eq!(align_of::<c_uint_fast32_t>(), c_alignof_uint_fast32_t);
181            assert_eq!(align_of::<c_uint_fast64_t>(), c_alignof_uint_fast64_t);
182            assert_eq!(align_of::<c_uint_least32_t>(), c_alignof_uint_least32_t);
183            assert_eq!(align_of::<ubounded>(), c_alignof_ubounded);
184            assert_eq!(align_of::<UWORD>(), c_alignof_UWORD);
185            assert_eq!(align_of::<sha256::CSha256Midstate>(), sha256::c_alignof_sha256_midstate);
186        }
187    }
188}