Skip to content

Conversation

@Bisht13
Copy link
Collaborator

@Bisht13 Bisht13 commented Sep 22, 2025

Summary

Adds a new provekit-ffi crate that provides C-compatible FFI bindings for ProveKit, enabling integration with multiple programming languages and platforms including mobile (iOS, Android), desktop, web, and embedded systems.

Features

  • C ABI Compatibility: All functions use C-compatible types and calling conventions
  • Memory Management: Safe buffer management with explicit allocation/deallocation via PKBuf
  • Multiple Output Formats: Support for binary file output and JSON in-memory output
  • Error Handling: Comprehensive error codes (PKError enum) with clear semantics
  • Cross-Platform: Compiles as a static library for iOS, Android, desktop, and embedded targets

API

Functions

Function Description
pk_init() Initialize the library (call once before using other functions)
pk_prove_to_file() Generate proof and write to file
pk_prove_to_json() Generate proof and return as JSON string in memory buffer
pk_free_buf() Free buffers returned by ProveKit functions

Error Codes

Code Value Description
PK_SUCCESS 0 Operation successful
PK_INVALID_INPUT 1 Invalid input parameters
PK_SCHEME_READ_ERROR 2 Failed to read scheme file
PK_WITNESS_READ_ERROR 3 Failed to read witness/input file
PK_PROOF_ERROR 4 Failed to generate proof
PK_SERIALIZATION_ERROR 5 Failed to serialize output
PK_UTF8_ERROR 6 UTF-8 conversion error
PK_FILE_WRITE_ERROR 7 File write error

Additional Changes

  • Updated CI workflow to use nightly-2025-10-20 matching rust-toolchain.toml
  • Fixed minor clippy warnings in provekit-common

@Bisht13 Bisht13 force-pushed the feat/provekit-ffi branch 2 times, most recently from 32b11e7 to e1044b2 Compare September 22, 2025 18:36
@Bisht13 Bisht13 force-pushed the feat/provekit-ffi branch 3 times, most recently from af6beed to 6f62ea3 Compare October 30, 2025 22:09
@Bisht13 Bisht13 requested a review from yash25198 January 13, 2026 15:20
- Update CI workflow to use nightly-2025-10-20 matching rust-toolchain.toml
- Fix MSRV warning: remove const from num_entries (requires Rust 1.87+)
- Fix doc-lazy-continuation warning in witness_builder.rs
- Fix needless_borrows_for_generic_args in FFI prove functions
Wrap FFI functions with catch_panic to prevent undefined behavior
from stack unwinding across FFI boundary. This is critical for
mobile platforms where panics must not propagate to C/Swift/Kotlin.
Allows host applications to provide custom memory allocation functions
for memory tracking and management. Falls back to system allocator when
not configured. Optimized for minimal overhead in the default case.
/// # Safety
///
/// The caller must ensure that `ptr` is a valid null-terminated C string.
pub unsafe fn c_str_to_str(ptr: *const c_char) -> Result<&'static str, PKError> {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Returns 'static lifetime but the underlying C string has no such guarantee if the caller frees the string while Rust code holds the reference.

#[no_mangle]
pub unsafe extern "C" fn pk_free_buf(buf: PKBuf) {
if !buf.ptr.is_null() && buf.len > 0 {
drop(Vec::from_raw_parts(buf.ptr, buf.len, buf.len));
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the original Vec had capacity > len, we're reconstructing with wrong capacity.
example :

let mut v: Vec<u8> = Vec::with_capacity(100);  // capacity = 100
v.push(1);
v.push(2);
v.push(3);
// Now: len = 3, capacity = 100

and then in types.rs

pub fn from_vec(mut v: Vec<u8>) -> Self {
    let ptr = v.as_mut_ptr();
    let len = v.len();          // len = 3
    std::mem::forget(v);        // capacity (100) 
    Self { ptr, len }           // PKBuf { ptr, len: 3 } 
}

and then pk_free_buf reconstructs with wrong capacity

drop(Vec::from_raw_parts(buf.ptr, buf.len, buf.len));
// len=3    cap=3 (was 100)

the allocator allocated 100 bytes but only 3 bytes were freed

catch_panic(PKError::ProofError.into(), || {
let out_buf = match out_buf.as_mut() {
Some(buf) => buf,
None => return PKError::InvalidInput.into(),
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

unreachable condition

serde.workspace = true
serde_json.workspace = true
postcard.workspace = true
tracing.workspace = true
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

unused dependency

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants