From df61fe0dc4f76194f1fdac39dbd2f7e76de75482 Mon Sep 17 00:00:00 2001 From: sanket1729 Date: Thu, 15 Dec 2022 03:49:18 -0800 Subject: [PATCH 1/3] Rename filenames --- simplicity-sys/README.md | 6 +++--- .../{vendor_simplicity.sh => vendor-simplicity.sh} | 0 2 files changed, 3 insertions(+), 3 deletions(-) rename simplicity-sys/{vendor_simplicity.sh => vendor-simplicity.sh} (100%) diff --git a/simplicity-sys/README.md b/simplicity-sys/README.md index aec99af5..da53f6c5 100644 --- a/simplicity-sys/README.md +++ b/simplicity-sys/README.md @@ -7,13 +7,13 @@ This crate provides Rust definitions for the FFI structures and methods. ## Vendoring -The default build process is to build using the vendored libsecp256k1 sources in +The default build process is to build using the vendored simplicity sources in the depend folder. There is no support for symbols yet. To update the vendored sources, use the `vendor-simplicity.sh` script: ``` -$ ./vendor-libsecp.sh depend +$ ./vendor-simplicity.sh depend ``` -- Where `` is the git revision of libsecp256k1 to checkout. \ No newline at end of file +- Where `` is the git revision of ElementsProject/simplicity to checkout. \ No newline at end of file diff --git a/simplicity-sys/vendor_simplicity.sh b/simplicity-sys/vendor-simplicity.sh similarity index 100% rename from simplicity-sys/vendor_simplicity.sh rename to simplicity-sys/vendor-simplicity.sh From e9a6d417b2e2732c198eb66f574314b3fb2b29a1 Mon Sep 17 00:00:00 2001 From: sanket1729 Date: Mon, 28 Nov 2022 01:46:12 -0800 Subject: [PATCH 2/3] Add wrappers to the C library for better interfacing --- simplicity-sys/build.rs | 2 + simplicity-sys/depend/env.c | 76 +++++++++++++++++++++++++++++++++ simplicity-sys/depend/wrapper.c | 45 +++++++++++++++++++ 3 files changed, 123 insertions(+) create mode 100644 simplicity-sys/depend/env.c create mode 100644 simplicity-sys/depend/wrapper.c diff --git a/simplicity-sys/build.rs b/simplicity-sys/build.rs index 63f1cef8..41d5fe6f 100644 --- a/simplicity-sys/build.rs +++ b/simplicity-sys/build.rs @@ -43,6 +43,8 @@ fn main() { .flag_if_supported("-fno-inline-functions") .files(files) .files(test_files) + .file(Path::new("depend/wrapper.c")) + .file(Path::new("depend/env.c")) .include(include) .compile("simplicity.a"); } diff --git a/simplicity-sys/depend/env.c b/simplicity-sys/depend/env.c new file mode 100644 index 00000000..34feb845 --- /dev/null +++ b/simplicity-sys/depend/env.c @@ -0,0 +1,76 @@ +#include +#include +#include "simplicity/elements/env.h" +#include "simplicity/primitive/elements/primitive.h" + +const size_t c_sizeof_rawBuffer = sizeof(rawBuffer); +const size_t c_sizeof_rawOutput = sizeof(rawOutput); +const size_t c_sizeof_rawInput = sizeof(rawInput); +const size_t c_sizeof_rawTransaction = sizeof(rawTransaction); +const size_t c_sizeof_rawTapEnv = sizeof(rawTapEnv); +const size_t c_sizeof_txEnv = sizeof(txEnv); + +const size_t c_alignof_rawBuffer = alignof(rawBuffer); +const size_t c_alignof_rawOutput = alignof(rawOutput); +const size_t c_alignof_rawInput = alignof(rawInput); +const size_t c_alignof_rawTransaction = alignof(rawTransaction); +const size_t c_alignof_rawTapEnv = alignof(rawTapEnv); +const size_t c_alignof_txEnv = alignof(txEnv); + +void c_set_rawBuffer(rawBuffer *result, const unsigned char *buf, unsigned int len) +{ + *result = (rawBuffer){.buf = buf, .len = len}; +} + +void c_set_rawOutput(rawOutput *result, const unsigned char *asset, const unsigned char *value, const unsigned char *nonce, const rawBuffer *scriptPubKey, + const rawBuffer *surjectionProof, const rawBuffer *rangeProof) +{ + *result = (rawOutput){.asset = asset, .value = value, .nonce = nonce, .scriptPubKey = *scriptPubKey, .surjectionProof = *surjectionProof, .rangeProof = *rangeProof}; +} + +void c_set_rawInput(rawInput *result, const rawBuffer *annex, const unsigned char *pegin, const rawBuffer *scriptSig, + const unsigned char *prevTxid, unsigned int prevIx, + const unsigned char *asset, const unsigned char *value, const rawBuffer *scriptPubKey, + unsigned int sequence, + const unsigned char *blindingNonce, const unsigned char *assetEntropy, const unsigned char *amount, const unsigned char *inflationKeys, + const rawBuffer *amountRangePrf, const rawBuffer *inflationKeysRangePrf) +{ + *result = (rawInput){.annex = annex, .scriptSig = *scriptSig, .prevTxid = prevTxid, .pegin = pegin, .issuance = {.blindingNonce = blindingNonce, .assetEntropy = assetEntropy, .amount = amount, .inflationKeys = inflationKeys, .amountRangePrf = *amountRangePrf, .inflationKeysRangePrf = *inflationKeysRangePrf}, .txo = {.asset = asset, .value = value, .scriptPubKey = *scriptPubKey}, .prevIx = prevIx, .sequence = sequence}; +} + +void c_set_rawTransaction(rawTransaction *result, unsigned int version, + const rawInput *input, unsigned int numInputs, + const rawOutput *output, unsigned int numOutputs, + unsigned int lockTime) +{ + *result = (rawTransaction){ + .version = version, + .input = input, + .numInputs = numInputs, + .output = output, + .numOutputs = numOutputs, + .lockTime = lockTime, + }; +} + +void c_set_rawTapEnv(rawTapEnv *result, const unsigned char *controlBlock, unsigned char branchLen, const unsigned char *scriptCMR) +{ + *result = (rawTapEnv){.controlBlock = controlBlock, .branchLen = branchLen, .scriptCMR = scriptCMR}; +} + +void c_set_txEnv(txEnv *result, const transaction *tx, const tapEnv *taproot, const unsigned char *genesisHash, unsigned int ix) +{ + sha256_midstate genesis; + sha256_toMidstate(genesis.s, genesisHash); + *result = build_txEnv(tx, taproot, &genesis, ix); +} + +void c_free_tapEnv(tapEnv *env) +{ + free(env); +} + +void c_free_transaction(transaction *tx) +{ + free(tx); +} diff --git a/simplicity-sys/depend/wrapper.c b/simplicity-sys/depend/wrapper.c new file mode 100644 index 00000000..5f24247b --- /dev/null +++ b/simplicity-sys/depend/wrapper.c @@ -0,0 +1,45 @@ +#ifndef WRAPPERS_H +#define WRAPPERS_H +#include "simplicity/frame.h" + +#include + +const size_t c_sizeof_UWORD = sizeof(UWORD); +const size_t c_sizeof_frameItem = sizeof(frameItem); + +const size_t c_alignof_UWORD = alignof(UWORD); +const size_t c_alignof_frameItem = alignof(frameItem); + +void c_initReadFrame(frameItem *frame, size_t n, UWORD *from) +{ + *frame = initReadFrame(n, from); +} + +void c_initWriteFrame(frameItem *frame, size_t n, UWORD *from) +{ + *frame = initWriteFrame(n, from); +} + +/* Expose readBit. Internal readBit is static inline. */ +bool c_readBit(frameItem *frame) +{ + return readBit(frame); +} + +/* Expose writeBit. Internal writeBit is static inline. */ +void c_writeBit(frameItem *frame, bool bit) +{ + writeBit(frame, bit); +} + +void c_forwardBits(frameItem *frame, size_t n) +{ + forwardBits(frame, n); +} + +void c_skipBits(frameItem *frame, size_t n) +{ + skipBits(frame, n); +} + +#endif \ No newline at end of file From 987ade1e243c10af510c4aa604879cbc871da996 Mon Sep 17 00:00:00 2001 From: sanket1729 Date: Mon, 28 Nov 2022 01:52:41 -0800 Subject: [PATCH 3/3] Expose FFI bindings to jets --- simplicity-sys/src/c_jets/c_env.rs | 256 ++++++++++++++++++++++ simplicity-sys/src/c_jets/c_frame.rs | 49 +++++ simplicity-sys/src/c_jets/frame_ffi.rs | 30 +++ simplicity-sys/src/c_jets/jets_ffi.rs | 9 + simplicity-sys/src/c_jets/jets_wrapper.rs | 11 + simplicity-sys/src/c_jets/mod.rs | 59 +++++ simplicity-sys/src/lib.rs | 2 + 7 files changed, 416 insertions(+) create mode 100644 simplicity-sys/src/c_jets/c_env.rs create mode 100644 simplicity-sys/src/c_jets/c_frame.rs create mode 100644 simplicity-sys/src/c_jets/frame_ffi.rs create mode 100644 simplicity-sys/src/c_jets/jets_ffi.rs create mode 100644 simplicity-sys/src/c_jets/jets_wrapper.rs create mode 100644 simplicity-sys/src/c_jets/mod.rs diff --git a/simplicity-sys/src/c_jets/c_env.rs b/simplicity-sys/src/c_jets/c_env.rs new file mode 100644 index 00000000..713b5db8 --- /dev/null +++ b/simplicity-sys/src/c_jets/c_env.rs @@ -0,0 +1,256 @@ +use std::os::raw::{c_uchar, c_uint}; + +use libc::size_t; + +/// Documentation of CRawInputData/CRawOutputData/CRawTapData/CRaw +/// Data structure for holding data that CTransaction points to. +/// +/// Why do we this special data structure? +/// 1. We need to keep the data in memory until the CTransaction is dropped. +/// 2. The memory is Transaction is not saved in the same format as required by FFI. +/// We use more ergonomics in rust to allow better UX which interfere with the FFI. For example, +/// the Value is stored as Tagged Union, but we require it to be a slice of bytes in elements format. +/// 3. Allocating inside FFI functions does not work because the memory is freed after the function returns. +/// 4. We only create allocations for data fields that are stored differently from the +/// consensus serialization format. +#[derive(Debug)] +pub struct RawOutputData { + pub asset: Vec, + pub value: Vec, + pub nonce: Vec, + pub surjection_proof: Vec, + pub range_proof: Vec, +} + +#[derive(Debug)] +#[repr(C)] +pub struct CRawBuffer { + pub ptr: *const c_uchar, + pub len: u32, +} + +/// Similar to [`CRawOutputData`], for inputs. +#[derive(Debug)] +pub struct RawInputData { + pub annex: Option>, + // issuance + pub issuance_amount: Vec, + pub issuance_inflation_keys: Vec, + pub amount_range_proof: Vec, + pub inflation_keys_range_proof: Vec, + // spent txo + pub asset: Vec, + pub value: Vec, +} + +/// Similar to [`CRawOutputData`], but for transaction +#[derive(Debug)] +pub struct RawTransactionData { + pub inputs: Vec, + pub outputs: Vec, +} + +#[derive(Debug)] +#[repr(C)] +pub struct CRawOutput { + asset: *const c_uchar, + value: *const c_uchar, + nonce: *const c_uchar, + script_pubkey: CRawBuffer, + surjection_proof: CRawBuffer, + range_proof: CRawBuffer, +} + +#[derive(Debug)] +#[repr(C)] +pub struct CRawInput { + annex: *const CRawBuffer, + prev_txid: *const c_uchar, + pegin: *const c_uchar, + // issuance + blinding_nonce: *const c_uchar, + asset_entropy: *const c_uchar, + amount: *const c_uchar, + inflation_keys: *const c_uchar, + amount_range_proof: CRawBuffer, + inflation_keys_range_proof: CRawBuffer, + // spent txo + asset: *const c_uchar, + value: *const c_uchar, + script_pubkey: CRawBuffer, + // inputs + script_sig: CRawBuffer, + prev_txout_index: u32, + sequence: u32, +} + +#[derive(Debug)] +#[repr(C)] +pub struct CRawTransaction { + inputs: *const CRawInput, + outputs: *const CRawOutput, + version: u32, + locktime: u32, + n_inputs: u32, + n_outputs: u32, +} + +#[derive(Debug)] +#[repr(C)] +pub struct CRawTapEnv { + control_block: *const c_uchar, + script_cmr: *const c_uchar, + branch_len: u8, +} + +#[derive(Debug)] +pub enum CTransaction {} + +#[derive(Debug)] +#[repr(C)] +pub struct CSha256 { + pub data: [u32; 8], +} + +#[derive(Debug)] +#[repr(C)] +pub struct CElementsTxEnv { + tx: *const CTransaction, + taproot: *const CTapEnv, + genesis_hash: CSha256, + sighash_all: CSha256, + ix: usize, // This is uint_fast32_t in C, which is usize for 32/64 bits +} + +#[derive(Debug)] +pub enum CTapEnv {} + +extern "C" { + + pub static c_sizeof_rawBuffer: size_t; + pub static c_sizeof_rawOutput: size_t; + pub static c_sizeof_rawInput: size_t; + pub static c_sizeof_rawTransaction: size_t; + pub static c_sizeof_rawTapEnv: size_t; + pub static c_sizeof_txEnv: size_t; + + pub static c_alignof_rawBuffer: size_t; + pub static c_alignof_rawOutput: size_t; + pub static c_alignof_rawInput: size_t; + pub static c_alignof_rawTransaction: size_t; + pub static c_alignof_rawTapEnv: size_t; + pub static c_alignof_txEnv: size_t; + + pub fn c_set_rawBuffer(res: *mut CRawBuffer, buf: *const c_uchar, len: c_uint); + pub fn c_set_rawOutput( + res: *mut CRawOutput, + asset: *const c_uchar, + value: *const c_uchar, + nonce: *const c_uchar, + scriptPubKey: *const CRawBuffer, + surjectionProof: *const CRawBuffer, + rangeProof: *const CRawBuffer, + ); + pub fn c_set_rawInput( + result: *mut CRawInput, + annex: *const CRawBuffer, + pegin: *const c_uchar, + scriptSig: *const CRawBuffer, + prevTxid: *const c_uchar, + prevIx: c_uint, + asset: *const c_uchar, + value: *const c_uchar, + scriptPubKey: *const CRawBuffer, + sequence: c_uint, + blindingNonce: *const c_uchar, + assetEntropy: *const c_uchar, + amount: *const c_uchar, + inflationKeys: *const c_uchar, + amountRangePrf: *const CRawBuffer, + inflationKeysRangePrf: *const CRawBuffer, + ); + + pub fn c_set_rawTransaction( + result: *mut CRawTransaction, + version: c_uint, + input: *const CRawInput, + numInputs: c_uint, + output: *const CRawOutput, + numOutputs: c_uint, + lockTime: c_uint, + ); + pub fn c_set_rawTapEnv( + result: *mut CRawTapEnv, + controlBlock: *const c_uchar, + branchLen: c_uchar, + scriptCMR: *const c_uchar, + ); + pub fn c_set_txEnv( + result: *mut CElementsTxEnv, + tx: *const CTransaction, + taproot: *const CTapEnv, + genesisHash: *const c_uchar, + ix: c_uint, + ); + pub fn elements_simplicity_mallocTapEnv(rawEnv: *const CRawTapEnv) -> *mut CTapEnv; + pub fn elements_simplicity_mallocTransaction( + rawTx: *const CRawTransaction, + ) -> *mut CTransaction; + pub fn c_free_transaction(tx: *mut CTransaction); + pub fn c_free_tapEnv(env: *mut CTapEnv); +} + +// Pointer must be manually free after dropping +impl Drop for CElementsTxEnv { + fn drop(&mut self) { + unsafe { + c_free_transaction(self.tx as *mut CTransaction); + c_free_tapEnv(self.taproot as *mut CTapEnv); + } + } +} + +impl CRawBuffer { + pub fn new(buf: &[c_uchar]) -> Self { + unsafe { + let mut raw_buffer = std::mem::MaybeUninit::::uninit(); + c_set_rawBuffer(raw_buffer.as_mut_ptr(), buf.as_ptr(), buf.len() as c_uint); + raw_buffer.assume_init() + } + } +} + +#[cfg(test)] +mod tests { + use std::mem::{align_of, size_of}; + + use crate::c_jets::{c_env::*, frame_ffi::*}; + + #[test] + fn test_sizes() { + unsafe { + assert_eq!(size_of::(), c_sizeof_UWORD); + assert_eq!(size_of::(), c_sizeof_frameItem); + assert_eq!(size_of::(), c_sizeof_rawBuffer); + assert_eq!(size_of::(), c_sizeof_rawInput); + assert_eq!(size_of::(), c_sizeof_rawOutput); + assert_eq!(size_of::(), c_sizeof_rawTransaction); + assert_eq!(size_of::(), c_sizeof_rawTapEnv); + assert_eq!(size_of::(), c_sizeof_txEnv); + } + } + + #[test] + fn test_aligns() { + unsafe { + assert_eq!(align_of::(), c_alignof_UWORD); + assert_eq!(align_of::(), c_alignof_frameItem); + assert_eq!(align_of::(), c_alignof_rawBuffer); + assert_eq!(align_of::(), c_alignof_rawInput); + assert_eq!(align_of::(), c_alignof_rawOutput); + assert_eq!(align_of::(), c_alignof_rawTransaction); + assert_eq!(align_of::(), c_alignof_rawTapEnv); + assert_eq!(align_of::(), c_alignof_txEnv); + } + } +} diff --git a/simplicity-sys/src/c_jets/c_frame.rs b/simplicity-sys/src/c_jets/c_frame.rs new file mode 100644 index 00000000..64060940 --- /dev/null +++ b/simplicity-sys/src/c_jets/c_frame.rs @@ -0,0 +1,49 @@ +//! High level APIs to creating read/write CFrames +//! + +use super::frame_ffi; +use super::frame_ffi::CFrameItem; + +impl CFrameItem { + /// Allocate a new frame item with dummy values + unsafe fn new_unchecked() -> Self { + Self { + edge: std::ptr::null(), + len: 0, + } + } + + /// Initialize a new read frame. + /// 'n' is the number of cells for the read frame. + /// 'from' is a pointer to the beginning of the new slice for the array of u8 to hold the frame's cells. + /// + /// Note: The C implementation uses array of UWORD for `from`. UWORD maps to uint_fast16_t which + /// maps to usize on both 32-bit and 64-bit platforms. + pub unsafe fn new_read(n: usize, from: *const usize) -> Self { + // Allocate a new vector of required size + let mut frame = CFrameItem::new_unchecked(); + frame_ffi::c_initReadFrame(&mut frame, n, from); + frame + } + + /// Initialize a new write frame. + /// 'n' is the number of cells for the write frame. + /// 'from' is a pointer to the one-past-the-end of the new slice for the array of UWORDS to hold the frame's cells. + pub unsafe fn new_write(n: usize, from: *mut usize) -> Self { + // Allocate a new vector of required size + let mut frame = CFrameItem::new_unchecked(); + frame_ffi::c_initWriteFrame(&mut frame, n, from); + frame + } +} + +// Number of uwords required to hold n bits +pub fn round_u_word(n: usize) -> usize { + unsafe { + (n + 8 * frame_ffi::c_sizeof_UWORD - 1) as usize / (8 * frame_ffi::c_sizeof_UWORD as usize) + } +} + +pub fn ffi_bytes_size(n: usize) -> usize { + unsafe { round_u_word(n) * frame_ffi::c_sizeof_UWORD } +} diff --git a/simplicity-sys/src/c_jets/frame_ffi.rs b/simplicity-sys/src/c_jets/frame_ffi.rs new file mode 100644 index 00000000..99e832ab --- /dev/null +++ b/simplicity-sys/src/c_jets/frame_ffi.rs @@ -0,0 +1,30 @@ +//! Frame related FFI bindings and data structures + +use std::os::raw::c_uchar; + +use libc::size_t; + +/// FrameItem for C FFI. +/// This type is only used to pass data to the C FFI. +#[derive(Debug)] +#[repr(C)] +pub struct CFrameItem { + pub edge: *const c_uchar, + pub len: size_t, +} + +extern "C" { + pub static c_sizeof_frameItem: size_t; + pub static c_sizeof_UWORD: size_t; + + pub static c_alignof_frameItem: size_t; + pub static c_alignof_UWORD: size_t; + + pub(crate) fn c_initWriteFrame(frame: &mut CFrameItem, n: size_t, from: *const size_t); + pub(crate) fn c_initReadFrame(frame: &mut CFrameItem, n: size_t, from: *const size_t); + + pub fn c_readBit(frame: &mut CFrameItem) -> bool; + pub fn c_writeBit(frame: &mut CFrameItem, bit: bool); + pub fn c_forwardBits(frame: &mut CFrameItem, n: usize); + pub fn c_skipBits(frame: &mut CFrameItem, n: usize); +} diff --git a/simplicity-sys/src/c_jets/jets_ffi.rs b/simplicity-sys/src/c_jets/jets_ffi.rs new file mode 100644 index 00000000..868c61c6 --- /dev/null +++ b/simplicity-sys/src/c_jets/jets_ffi.rs @@ -0,0 +1,9 @@ +use std::os::raw::c_void; + +use super::c_env::CElementsTxEnv; +use super::frame_ffi::CFrameItem; + +extern "C" { + pub fn add_32(dst: *mut CFrameItem, src: CFrameItem, env: *const c_void) -> bool; + pub fn lock_time(dst: *mut CFrameItem, src: CFrameItem, env: *const CElementsTxEnv) -> bool; +} diff --git a/simplicity-sys/src/c_jets/jets_wrapper.rs b/simplicity-sys/src/c_jets/jets_wrapper.rs new file mode 100644 index 00000000..4cab9fb0 --- /dev/null +++ b/simplicity-sys/src/c_jets/jets_wrapper.rs @@ -0,0 +1,11 @@ +use crate::CElementsTxEnv; + +use super::{frame_ffi::CFrameItem, jets_ffi}; + +pub fn add_32(dst: &mut CFrameItem, src: CFrameItem, _env: &()) -> bool { + unsafe { jets_ffi::add_32(dst, src, std::ptr::null()) } +} + +pub fn lock_time(dst: &mut CFrameItem, src: CFrameItem, env: &CElementsTxEnv) -> bool { + unsafe { jets_ffi::lock_time(dst, src, env) } +} diff --git a/simplicity-sys/src/c_jets/mod.rs b/simplicity-sys/src/c_jets/mod.rs new file mode 100644 index 00000000..b7553efc --- /dev/null +++ b/simplicity-sys/src/c_jets/mod.rs @@ -0,0 +1,59 @@ +//! FFI related to jets +// Typically, the only things in the sys crate are the +// FFI bindings. The high level code should be in the +// main crate. +// We don't follow this practice in the library of as now + +pub mod c_env; +pub mod c_frame; +pub mod frame_ffi; +pub mod jets_ffi; +pub mod jets_wrapper; + +pub use c_env::{CElementsTxEnv, CTapEnv, CTransaction}; +pub use c_frame::{ffi_bytes_size, round_u_word}; +pub use frame_ffi::CFrameItem; + +use crate::c_jets::c_env::{CRawBuffer, CRawInput, CRawOutput, CRawTapEnv, CRawTransaction}; + +/// sanity checks for using the types. +/// We are not using the internal representation of the types at all, but +/// we do care about the size and alignments of the types. +/// +/// This will also us detect whenever there is a change in the underlying C representation +pub fn sanity_checks() -> bool { + unsafe { + // Check that UWORD maps correctly to usize. UWORD maps to uint_fast16_t + // which is at least 16 bits, and is the same size as usize on all + // platforms 32 and 64 platforms. + if std::mem::size_of::() != frame_ffi::c_sizeof_UWORD + || std::mem::align_of::() != frame_ffi::c_alignof_UWORD + { + return false; + } + + if std::mem::size_of::() != frame_ffi::c_sizeof_frameItem + || std::mem::size_of::() != c_env::c_sizeof_rawBuffer + || std::mem::size_of::() != c_env::c_sizeof_rawInput + || std::mem::size_of::() != c_env::c_sizeof_rawOutput + || std::mem::size_of::() != c_env::c_sizeof_rawTransaction + || std::mem::size_of::() != c_env::c_sizeof_txEnv + || std::mem::size_of::() != c_env::c_sizeof_rawTapEnv + { + return false; + } + + // Check alignments + if std::mem::align_of::() != frame_ffi::c_alignof_frameItem + || std::mem::align_of::() != c_env::c_alignof_rawBuffer + || std::mem::align_of::() != c_env::c_alignof_rawInput + || std::mem::align_of::() != c_env::c_alignof_rawOutput + || std::mem::align_of::() != c_env::c_alignof_rawTransaction + || std::mem::align_of::() != c_env::c_alignof_txEnv + || std::mem::align_of::() != c_env::c_alignof_rawTapEnv + { + return false; + } + } + true +} diff --git a/simplicity-sys/src/lib.rs b/simplicity-sys/src/lib.rs index a8088074..a469ba11 100644 --- a/simplicity-sys/src/lib.rs +++ b/simplicity-sys/src/lib.rs @@ -14,6 +14,8 @@ mod bitstream; mod bitstring; +pub mod c_jets; +pub use c_jets::{CElementsTxEnv, CFrameItem, CTapEnv, CTransaction}; pub mod dag; pub mod error; pub mod test;