Skip to content

Commit f1299d5

Browse files
authored
Merge pull request #19 from zkmopro/feat/dynamic-wtns-buffer
feat: dynamic buffer allocation for wtns generation
2 parents 8610fef + 9991693 commit f1299d5

1 file changed

Lines changed: 48 additions & 12 deletions

File tree

witnesscalc_adapter/src/lib.rs

Lines changed: 48 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,10 @@ macro_rules! witness {
3737
}
3838
$crate::paste::item! {
3939
pub fn [<$x _witness>](json_input: &str) -> $crate::__macro_deps::anyhow::Result<Vec<u8>> {
40+
// FFI return codes
41+
const WITNESSCALC_OK: std::ffi::c_int = 0x0;
42+
const WITNESSCALC_ERROR_SHORT_BUFFER: std::ffi::c_int = 0x2;
43+
4044
println!("Generating witness for circuit {}", stringify!($x));
4145
unsafe {
4246
let json_input = std::ffi::CString::new(json_input).map_err(|e| $crate::__macro_deps::anyhow::anyhow!("Failed to convert JSON input to CString: {}", e))?;
@@ -45,33 +49,65 @@ macro_rules! witness {
4549
let circuit_buffer = [<$x _CIRCUIT_DATA>].as_ptr() as *const std::ffi::c_char;
4650
let circuit_size = [<$x _CIRCUIT_DATA>].len() as std::ffi::c_ulong;
4751

48-
//TODO dynamically allocate the buffer?
49-
let mut wtns_buffer = vec![0u8; 100 * 1024 * 1024]; // 8 MB buffer
50-
let mut wtns_size: std::ffi::c_ulong = wtns_buffer.len() as std::ffi::c_ulong;
51-
5252
let mut error_msg = vec![0u8; 256]; // Error message buffer
5353
let error_msg_ptr = error_msg.as_mut_ptr() as *mut std::ffi::c_char;
5454

55-
let result = [<witnesscalc_ $x>](
55+
// Two-pass dynamic allocation:
56+
// Pass 1: Probe with small buffer to query required size
57+
let mut probe_buffer = vec![0u8; 1024]; // 1 KB probe buffer
58+
let mut wtns_size: std::ffi::c_ulong = probe_buffer.len() as std::ffi::c_ulong;
59+
60+
let result = [<witnesscalc_ $x>](
5661
circuit_buffer,
5762
circuit_size,
5863
json_input.as_ptr(),
5964
json_size,
60-
wtns_buffer.as_mut_ptr() as *mut _,
65+
probe_buffer.as_mut_ptr() as *mut _,
6166
&mut wtns_size as *mut _,
62-
error_msg.as_mut_ptr() as *mut _,
67+
error_msg_ptr,
6368
error_msg.len() as u64,
6469
);
6570

66-
if result != 0 {
71+
// Pass 2: If buffer too small, allocate exact size and retry
72+
let final_buffer = if result == WITNESSCALC_ERROR_SHORT_BUFFER {
73+
// wtns_size now contains the required minimum size
74+
let required_size = wtns_size as usize;
75+
println!("Witness requires {} bytes, allocating and retrying...", required_size);
76+
77+
let mut wtns_buffer = vec![0u8; required_size];
78+
let mut wtns_size: std::ffi::c_ulong = required_size as std::ffi::c_ulong;
79+
80+
let result = [<witnesscalc_ $x>](
81+
circuit_buffer,
82+
circuit_size,
83+
json_input.as_ptr(),
84+
json_size,
85+
wtns_buffer.as_mut_ptr() as *mut _,
86+
&mut wtns_size as *mut _,
87+
error_msg_ptr,
88+
error_msg.len() as u64,
89+
);
90+
91+
if result != WITNESSCALC_OK {
92+
let error_string = std::ffi::CStr::from_ptr(error_msg_ptr)
93+
.to_string_lossy()
94+
.into_owned();
95+
return Err($crate::__macro_deps::anyhow::anyhow!("Witness generation failed: {}", error_string));
96+
}
97+
98+
wtns_buffer[..wtns_size as usize].to_vec()
99+
} else if result == WITNESSCALC_OK {
100+
// Success on first try with probe buffer (small witness)
101+
probe_buffer[..wtns_size as usize].to_vec()
102+
} else {
103+
// Other error
67104
let error_string = std::ffi::CStr::from_ptr(error_msg_ptr)
68105
.to_string_lossy()
69106
.into_owned();
70-
return Err($crate::__macro_deps::anyhow::anyhow!("Proof generation failed: {}", error_string));
71-
}
107+
return Err($crate::__macro_deps::anyhow::anyhow!("Witness generation failed: {}", error_string));
108+
};
72109

73-
let wtns_buffer = &wtns_buffer[..wtns_size as usize];
74-
Ok(wtns_buffer.to_vec())
110+
Ok(final_buffer)
75111
}
76112
}
77113
}

0 commit comments

Comments
 (0)