Skip to main content

simplicity_sys/c_jets/c_env/
elements.rs

1// SPDX-License-Identifier: CC0-1.0
2
3use hashes::sha256;
4
5use crate::ffi::sha256::CSha256Midstate;
6use crate::ffi::{c_size_t, c_uchar, c_uint, c_uint_fast32_t};
7
8#[derive(Debug)]
9#[repr(C)]
10pub struct CRawBuffer {
11    pub ptr: *const c_uchar,
12    pub len: u32,
13}
14
15#[derive(Debug)]
16#[repr(C)]
17pub struct CRawOutput<'raw> {
18    pub asset: Option<&'raw [c_uchar; 33]>,
19    pub value: *const c_uchar,
20    pub nonce: Option<&'raw [c_uchar; 33]>,
21    pub script_pubkey: CRawBuffer,
22    pub surjection_proof: CRawBuffer,
23    pub range_proof: CRawBuffer,
24}
25
26#[repr(C)]
27pub struct CRawInputIssuance<'raw> {
28    pub blinding_nonce: Option<&'raw [c_uchar; 32]>,
29    pub asset_entropy: Option<&'raw [c_uchar; 32]>,
30    pub amount: *const c_uchar,
31    pub inflation_keys: *const c_uchar,
32    pub amount_range_proof: CRawBuffer,
33    pub inflation_keys_range_proof: CRawBuffer,
34}
35
36impl<'raw> CRawInputIssuance<'raw> {
37    /// Constructs a raw input issuance structure corresponding to "no issuance".
38    pub fn no_issuance() -> Self {
39        Self {
40            blinding_nonce: None,
41            asset_entropy: None,
42            amount: core::ptr::null(),
43            inflation_keys: core::ptr::null(),
44            amount_range_proof: CRawBuffer::new(&[]),
45            inflation_keys_range_proof: CRawBuffer::new(&[]),
46        }
47    }
48}
49
50#[repr(C)]
51pub struct CRawInputTxo<'raw> {
52    pub asset: Option<&'raw [c_uchar; 33]>,
53    pub value: *const c_uchar,
54    pub script_pubkey: CRawBuffer,
55}
56
57#[repr(C)]
58pub struct CRawInput<'raw> {
59    pub annex: *const CRawBuffer,
60    pub prev_txid: &'raw [c_uchar; 32],
61    pub pegin: Option<&'raw [c_uchar; 32]>,
62    pub issuance: CRawInputIssuance<'raw>,
63    pub txo: CRawInputTxo<'raw>,
64    pub script_sig: CRawBuffer,
65    pub prev_txout_index: u32,
66    pub sequence: u32,
67}
68
69#[derive(Debug)]
70#[repr(C)]
71pub struct CRawTransaction<'raw> {
72    pub txid: &'raw [c_uchar; 32],
73    pub inputs: *const CRawInput<'raw>,
74    pub outputs: *const CRawOutput<'raw>,
75    pub n_inputs: u32,
76    pub n_outputs: u32,
77    pub version: u32,
78    pub locktime: u32,
79}
80
81#[derive(Debug)]
82#[repr(C)]
83pub struct CRawTapEnv {
84    pub control_block: *const c_uchar,
85    pub script_cmr: *const c_uchar,
86    pub branch_len: u8,
87}
88
89#[repr(C)]
90pub struct CTransaction {
91    _data: (),
92}
93
94#[derive(Debug)]
95#[repr(C)]
96pub struct CTxEnv {
97    tx: *const CTransaction,
98    taproot: *const CTapEnv,
99    genesis_hash: CSha256Midstate,
100    sighash_all: CSha256Midstate,
101    ix: c_uint_fast32_t,
102}
103
104#[repr(C)]
105pub struct CTapEnv {
106    _data: (),
107}
108
109extern "C" {
110    #[link_name = "rustsimplicity_0_8_c_sizeof_rawElementsBuffer"]
111    pub static c_sizeof_rawBuffer: c_size_t;
112    #[link_name = "rustsimplicity_0_8_c_sizeof_rawElementsOutput"]
113    pub static c_sizeof_rawOutput: c_size_t;
114    #[link_name = "rustsimplicity_0_8_c_sizeof_rawElementsInput"]
115    pub static c_sizeof_rawInput: c_size_t;
116    #[link_name = "rustsimplicity_0_8_c_sizeof_rawElementsTransaction"]
117    pub static c_sizeof_rawTransaction: c_size_t;
118    #[link_name = "rustsimplicity_0_8_c_sizeof_rawElementsTapEnv"]
119    pub static c_sizeof_rawTapEnv: c_size_t;
120    #[link_name = "rustsimplicity_0_8_c_sizeof_txEnv"]
121    pub static c_sizeof_txEnv: c_size_t;
122
123    #[link_name = "rustsimplicity_0_8_c_alignof_rawElementsBuffer"]
124    pub static c_alignof_rawBuffer: c_size_t;
125    #[link_name = "rustsimplicity_0_8_c_alignof_rawElementsOutput"]
126    pub static c_alignof_rawOutput: c_size_t;
127    #[link_name = "rustsimplicity_0_8_c_alignof_rawElementsInput"]
128    pub static c_alignof_rawInput: c_size_t;
129    #[link_name = "rustsimplicity_0_8_c_alignof_rawElementsTransaction"]
130    pub static c_alignof_rawTransaction: c_size_t;
131    #[link_name = "rustsimplicity_0_8_c_alignof_rawElementsTapEnv"]
132    pub static c_alignof_rawTapEnv: c_size_t;
133    #[link_name = "rustsimplicity_0_8_c_alignof_txEnv"]
134    pub static c_alignof_txEnv: c_size_t;
135
136    #[link_name = "rustsimplicity_0_8_c_set_txEnv"]
137    pub fn c_set_txEnv(
138        result: *mut CTxEnv,
139        tx: *const CTransaction,
140        taproot: *const CTapEnv,
141        genesisHash: *const c_uchar,
142        ix: c_uint,
143    );
144    #[link_name = "rustsimplicity_0_8_elements_mallocTapEnv"]
145    pub fn simplicity_mallocTapEnv(rawEnv: *const CRawTapEnv) -> *mut CTapEnv;
146    #[link_name = "rustsimplicity_0_8_elements_mallocTransaction"]
147    pub fn simplicity_mallocTransaction(rawTx: *const CRawTransaction) -> *mut CTransaction;
148}
149impl CTxEnv {
150    pub fn sighash_all(&self) -> sha256::Hash {
151        // This is a little bit sketchy, directly interpreting a midstate as a sha256 hash. Bit
152        // it is okay because sighash data is public and unambiguously encoded, so there is no
153        // risk of length-extension attacks.
154        let midstate: sha256::Midstate = self.sighash_all.into();
155        sha256::Hash::from_byte_array(midstate.to_parts().0)
156    }
157}
158
159// Pointer must be manually free after dropping
160impl Drop for CTxEnv {
161    fn drop(&mut self) {
162        unsafe {
163            crate::alloc::rust_0_8_free(self.tx as *mut u8);
164            crate::alloc::rust_0_8_free(self.taproot as *mut u8);
165        }
166    }
167}
168
169impl CRawBuffer {
170    pub fn new(buf: &[c_uchar]) -> Self {
171        Self {
172            ptr: buf.as_ptr(),
173            len: buf.len().try_into().expect("sane buffer lengths"),
174        }
175    }
176}
177
178#[cfg(test)]
179mod tests {
180    use core::mem::{align_of, size_of};
181
182    use crate::c_jets::frame_ffi::{c_alignof_frameItem, c_sizeof_frameItem, CFrameItem};
183
184    use super::*;
185
186    #[test]
187    fn test_sizes() {
188        unsafe {
189            assert_eq!(size_of::<CFrameItem>(), c_sizeof_frameItem);
190            assert_eq!(size_of::<CRawBuffer>(), c_sizeof_rawBuffer);
191            assert_eq!(size_of::<CRawInput>(), c_sizeof_rawInput);
192            assert_eq!(size_of::<CRawOutput>(), c_sizeof_rawOutput);
193            assert_eq!(size_of::<CRawTransaction>(), c_sizeof_rawTransaction);
194            assert_eq!(size_of::<CRawTapEnv>(), c_sizeof_rawTapEnv);
195            assert_eq!(size_of::<CTxEnv>(), c_sizeof_txEnv);
196        }
197    }
198
199    #[test]
200    fn test_aligns() {
201        unsafe {
202            assert_eq!(align_of::<CFrameItem>(), c_alignof_frameItem);
203            assert_eq!(align_of::<CRawBuffer>(), c_alignof_rawBuffer);
204            assert_eq!(align_of::<CRawInput>(), c_alignof_rawInput);
205            assert_eq!(align_of::<CRawOutput>(), c_alignof_rawOutput);
206            assert_eq!(align_of::<CRawTransaction>(), c_alignof_rawTransaction);
207            assert_eq!(align_of::<CRawTapEnv>(), c_alignof_rawTapEnv);
208            assert_eq!(align_of::<CTxEnv>(), c_alignof_txEnv);
209        }
210    }
211}