From 84d4b3597945819a63ac060a1f39e8f331d9ccb2 Mon Sep 17 00:00:00 2001 From: Mikerah Date: Thu, 8 Jan 2026 09:21:26 -0500 Subject: [PATCH 1/2] feat(ffi): add extract_quic_network FFI function for StoffelVM compatibility Add two new FFI functions to enable interoperability between mpc-protocols network types and external libraries like StoffelVM: - extract_quic_network(): Extracts Arc from NetworkOpaque and returns it as a boxed Arc pointer compatible with StoffelVM's hb_engine_new() function - free_raw_quic_network(): Frees the extracted pointer This solves the FFI type mismatch where mpc-protocols uses NetworkOpaque (wrapping GenericNetwork) while StoffelVM expects a raw Arc. Co-Authored-By: Claude Opus 4.5 --- mpc/src/ffi/c_bindings/network/mod.rs | 52 +++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/mpc/src/ffi/c_bindings/network/mod.rs b/mpc/src/ffi/c_bindings/network/mod.rs index 1a17aea..28a3a7b 100644 --- a/mpc/src/ffi/c_bindings/network/mod.rs +++ b/mpc/src/ffi/c_bindings/network/mod.rs @@ -1,5 +1,6 @@ pub mod fake_network; pub mod quic; +use std::ffi::c_void; use std::slice; use std::sync::Arc; @@ -94,3 +95,54 @@ pub extern "C" fn network_send( Err(e) => return e.into(), } } + +/// Extract raw QuicNetworkManager pointer for use with external libraries. +/// +/// This function extracts the inner `Arc` from a `NetworkOpaque` +/// pointer and returns it as a boxed Arc suitable for passing to libraries like StoffelVM +/// that expect a raw `Arc` pointer. +/// +/// # Arguments +/// * `network` - A pointer to NetworkOpaque (must wrap GenericNetwork::QuicNetworkManager) +/// +/// # Returns +/// * A pointer to a boxed `Arc`, or null if: +/// - The input pointer is null +/// - The network is not a QuicNetworkManager variant +/// +/// # Safety +/// * The caller must ensure `network` is a valid NetworkOpaque pointer +/// * The returned pointer must be freed with `free_raw_quic_network()` when no longer needed +/// * The original NetworkOpaque remains valid and must be freed separately +#[no_mangle] +pub extern "C" fn extract_quic_network(network: *mut NetworkOpaque) -> *mut c_void { + if network.is_null() { + return std::ptr::null_mut(); + } + let net = unsafe { &*(network as *mut GenericNetwork) }; + match net { + GenericNetwork::QuicNetworkManager(arc) => { + // Box the Arc for stable FFI pointer (matches StoffelVM expectation) + Box::into_raw(Box::new(Arc::clone(arc))) as *mut c_void + } + _ => std::ptr::null_mut(), + } +} + +/// Free a raw QuicNetworkManager pointer obtained from `extract_quic_network()`. +/// +/// # Arguments +/// * `ptr` - A pointer obtained from `extract_quic_network()` +/// +/// # Safety +/// * The pointer must have been obtained from `extract_quic_network()` +/// * The pointer must not have been freed already +/// * The pointer must not be used after this call +#[no_mangle] +pub extern "C" fn free_raw_quic_network(ptr: *mut c_void) { + if !ptr.is_null() { + unsafe { + let _ = Box::from_raw(ptr as *mut Arc); + } + } +} From 7bb122559cefb75839be3c0d199606029cfdb9d9 Mon Sep 17 00:00:00 2001 From: Mikerah Date: Thu, 8 Jan 2026 10:19:34 -0500 Subject: [PATCH 2/2] feat(ffi): add new_quic_network_with_party_id for MPC party ID mapping Add FFI function to create QUIC networks with specific party IDs. This is essential for MPC operations where parties need consistent IDs for handshakes and connection lookups. The existing new_quic_network() generates random UUID-based node_ids, which causes preprocessing failures when HoneyBadger tries to send to sequential party IDs (0, 1, 2, etc.). Changes: - Add new_quic_network_with_party_id(party_id, returned_connections) - Uses QuicNetworkManager::with_node_id(party_id) Co-Authored-By: Claude Opus 4.5 --- mpc/src/ffi/c_bindings/network/quic.rs | 27 ++++++++++++++++++++++++++ mpc/src/ffi/honey_badger_bindings.h | 13 +++++++++++++ 2 files changed, 40 insertions(+) diff --git a/mpc/src/ffi/c_bindings/network/quic.rs b/mpc/src/ffi/c_bindings/network/quic.rs index a716dcf..3080837 100644 --- a/mpc/src/ffi/c_bindings/network/quic.rs +++ b/mpc/src/ffi/c_bindings/network/quic.rs @@ -85,6 +85,33 @@ pub extern "C" fn new_quic_network( Box::into_raw(Box::new(quic_network)) as *mut QuicNetworkOpaque } +/// Creates a new QUIC network instance with a specific party ID +/// +/// This is essential for MPC operations where parties need consistent IDs. +/// The party_id will be used in handshakes and for connection lookups. +/// +/// # Arguments +/// * `party_id` - The party ID for this network node (e.g., 0, 1, 2, etc.) +/// * `returned_connections` - Output parameter for peer connections map +#[no_mangle] +pub extern "C" fn new_quic_network_with_party_id( + party_id: usize, + returned_connections: *mut *mut QuicPeerConnectionsOpaque, +) -> *mut QuicNetworkOpaque { + let quic_network = QuicNetwork { + quic_manager: QuicNetworkManager::with_node_id(party_id), + }; + let peer_connections = QuicPeerConnections { + connections: HashMap::new(), + }; + unsafe { + *returned_connections = + Box::into_raw(Box::new(peer_connections)) as *mut QuicPeerConnectionsOpaque; + } + + Box::into_raw(Box::new(quic_network)) as *mut QuicNetworkOpaque +} + /// Establishes a connection to a new peer /// /// This method initiates an outgoing connection to a peer at the specified address. diff --git a/mpc/src/ffi/honey_badger_bindings.h b/mpc/src/ffi/honey_badger_bindings.h index f6fd45e..ac9d6c9 100644 --- a/mpc/src/ffi/honey_badger_bindings.h +++ b/mpc/src/ffi/honey_badger_bindings.h @@ -279,6 +279,19 @@ void init_tls(void); */ struct QuicNetworkOpaque *new_quic_network(struct QuicPeerConnectionsOpaque **returned_connections); +/** + * Creates a new QUIC network instance with a specific party ID + * + * This is essential for MPC operations where parties need consistent IDs. + * The party_id will be used in handshakes and for connection lookups. + * + * # Arguments + * * `party_id` - The party ID for this network node (e.g., 0, 1, 2, etc.) + * * `returned_connections` - Output parameter for peer connections map + */ +struct QuicNetworkOpaque *new_quic_network_with_party_id(uintptr_t party_id, + struct QuicPeerConnectionsOpaque **returned_connections); + /** * Establishes a connection to a new peer *