@@ -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