@@ -22,10 +22,13 @@ use stark::prover::{IsStarkProver, Prover};
2222use stark:: traits:: AIR ;
2323use stark:: verifier:: { IsStarkVerifier , Verifier } ;
2424
25+ use crate :: VmProof ;
26+ use crate :: tables:: MaxRowsConfig ;
2527use crate :: tables:: trace_builder:: Traces ;
2628use crate :: tables:: types:: { GoldilocksExtension , GoldilocksField } ;
2729
2830use executor:: elf:: Elf ;
31+ use executor:: vm:: execution:: Executor ;
2932
3033// Import shared utilities
3134use crate :: VmAirs ;
@@ -83,6 +86,79 @@ fn prove_and_verify_vm_minimal(elf: &Elf, traces: &mut Traces) -> bool {
8386 )
8487}
8588
89+ /// Like [`crate::prove_with_options_and_inputs`] but with trimmed bitwise (TEST ONLY).
90+ ///
91+ /// ~100x faster than the production path. Same unsoundness caveats as
92+ /// [`Traces::from_elf_and_logs_minimal`]. The full preprocessed bitwise
93+ /// path is covered by `test_prove_elfs_all_instructions_64_full`.
94+ fn prove_vm_minimal ( elf_bytes : & [ u8 ] , private_inputs : & [ u8 ] , max_rows : & MaxRowsConfig ) -> VmProof {
95+ let proof_options = ProofOptions :: default_test_options ( ) ;
96+ let elf = Elf :: load ( elf_bytes) . expect ( "ELF load" ) ;
97+ let executor = Executor :: new ( & elf, private_inputs. to_vec ( ) ) . expect ( "executor" ) ;
98+ let result = executor. run ( ) . expect ( "execution" ) ;
99+ let mut traces =
100+ Traces :: from_elf_and_logs_minimal ( & elf, & result. logs , max_rows, private_inputs) . unwrap ( ) ;
101+ let table_counts = traces. table_counts ( ) ;
102+ let airs = VmAirs :: new (
103+ & elf,
104+ & proof_options,
105+ true ,
106+ & traces. page_configs ,
107+ & table_counts,
108+ ) ;
109+ let runtime_page_ranges = traces. runtime_page_ranges ( ) ;
110+ let proof = Prover :: multi_prove (
111+ airs. air_trace_pairs ( & mut traces) ,
112+ & mut DefaultTranscript :: < E > :: new ( & [ ] ) ,
113+ )
114+ . expect ( "prove" ) ;
115+ let num_private_input_pages = traces
116+ . page_configs
117+ . iter ( )
118+ . filter ( |c| c. is_private_input )
119+ . count ( ) ;
120+ VmProof {
121+ proof,
122+ runtime_page_ranges,
123+ table_counts,
124+ public_output : traces. public_output_bytes . clone ( ) ,
125+ num_private_input_pages,
126+ }
127+ }
128+
129+ /// Like [`crate::verify_with_options`] but matches the minimal bitwise AIR.
130+ ///
131+ /// Must be used to verify proofs from [`prove_vm_minimal`].
132+ fn verify_vm_minimal ( vm_proof : & VmProof , elf_bytes : & [ u8 ] ) -> bool {
133+ let proof_options = ProofOptions :: default_test_options ( ) ;
134+ let elf = Elf :: load ( elf_bytes) . expect ( "ELF load" ) ;
135+ let page_configs = Traces :: page_configs_from_elf_and_runtime (
136+ & elf,
137+ & vm_proof. runtime_page_ranges ,
138+ vm_proof. num_private_input_pages ,
139+ ) ;
140+ let airs = VmAirs :: new (
141+ & elf,
142+ & proof_options,
143+ true ,
144+ & page_configs,
145+ & vm_proof. table_counts ,
146+ ) ;
147+ let air_refs = airs. air_refs ( ) ;
148+ let expected_bus_balance = crate :: compute_expected_commit_bus_balance (
149+ & air_refs,
150+ & vm_proof. proof ,
151+ & vm_proof. public_output ,
152+ )
153+ . expect ( "fingerprint collision in test" ) ;
154+ Verifier :: multi_verify (
155+ & air_refs,
156+ & vm_proof. proof ,
157+ & mut DefaultTranscript :: < E > :: new ( & [ ] ) ,
158+ & expected_bus_balance,
159+ )
160+ }
161+
86162// =============================================================================
87163// Integration tests
88164// =============================================================================
@@ -157,8 +233,9 @@ fn test_cpu_only_no_bus() {
157233fn test_prove_elfs_sub_fast ( ) {
158234 let _ = env_logger:: builder ( ) . is_test ( true ) . try_init ( ) ;
159235 let ( elf, logs, _instructions) = run_asm_elf ( "sub" ) ;
160- // Use from_elf_and_logs to get PAGE and REGISTER tables for Memory bus
161- let mut traces = Traces :: from_elf_and_logs ( & elf, & logs, & Default :: default ( ) , & [ ] ) . unwrap ( ) ;
236+ // Use from_elf_and_logs_minimal to get PAGE and REGISTER tables for Memory bus
237+ let mut traces =
238+ Traces :: from_elf_and_logs_minimal ( & elf, & logs, & Default :: default ( ) , & [ ] ) . unwrap ( ) ;
162239
163240 assert ! (
164241 prove_and_verify_vm_minimal( & elf, & mut traces) ,
@@ -597,7 +674,8 @@ fn test_prove_elfs_test_xor_8() {
597674#[ test]
598675fn test_prove_elfs_test_lb_lh_8 ( ) {
599676 let ( elf, logs, _instructions) = run_asm_elf ( "test_lb_lh_8" ) ;
600- let mut traces = Traces :: from_elf_and_logs ( & elf, & logs, & Default :: default ( ) , & [ ] ) . unwrap ( ) ;
677+ let mut traces =
678+ Traces :: from_elf_and_logs_minimal ( & elf, & logs, & Default :: default ( ) , & [ ] ) . unwrap ( ) ;
601679 assert ! (
602680 prove_and_verify_vm_minimal( & elf, & mut traces) ,
603681 "test_lb_lh_8 failed"
@@ -607,7 +685,8 @@ fn test_prove_elfs_test_lb_lh_8() {
607685#[ test]
608686fn test_prove_elfs_test_sb_sh_8 ( ) {
609687 let ( elf, logs, _instructions) = run_asm_elf ( "test_sb_sh_8" ) ;
610- let mut traces = Traces :: from_elf_and_logs ( & elf, & logs, & Default :: default ( ) , & [ ] ) . unwrap ( ) ;
688+ let mut traces =
689+ Traces :: from_elf_and_logs_minimal ( & elf, & logs, & Default :: default ( ) , & [ ] ) . unwrap ( ) ;
611690 assert ! (
612691 !traces. memws. is_empty( ) ,
613692 "test_sb_sh_8 should produce MEMW rows for byte/halfword memory accesses"
@@ -624,7 +703,8 @@ fn test_prove_elfs_test_sb_sh_8() {
624703#[ test]
625704fn test_prove_elfs_lw_sw ( ) {
626705 let ( elf, logs, _instructions) = run_asm_elf ( "lw_sw" ) ;
627- let mut traces = Traces :: from_elf_and_logs ( & elf, & logs, & Default :: default ( ) , & [ ] ) . unwrap ( ) ;
706+ let mut traces =
707+ Traces :: from_elf_and_logs_minimal ( & elf, & logs, & Default :: default ( ) , & [ ] ) . unwrap ( ) ;
628708 assert ! (
629709 !traces. memw_aligneds. is_empty( ) ,
630710 "lw_sw should produce MEMW_A rows for aligned word accesses"
@@ -644,7 +724,8 @@ fn test_prove_elfs_lw_sw() {
644724#[ test]
645725fn test_prove_elfs_test_memw_split_ts ( ) {
646726 let ( elf, logs, _instructions) = run_asm_elf ( "test_memw_split_ts" ) ;
647- let mut traces = Traces :: from_elf_and_logs ( & elf, & logs, & Default :: default ( ) , & [ ] ) . unwrap ( ) ;
727+ let mut traces =
728+ Traces :: from_elf_and_logs_minimal ( & elf, & logs, & Default :: default ( ) , & [ ] ) . unwrap ( ) ;
648729 assert ! (
649730 !traces. memws. is_empty( ) ,
650731 "test_memw_split_ts should produce MEMW rows (split old_timestamps from sb+sb+lh)"
@@ -683,7 +764,8 @@ fn test_prove_elfs_all_branches_16() {
683764#[ test]
684765fn test_prove_elfs_all_loadstore_32 ( ) {
685766 let ( elf, logs, _instructions) = run_asm_elf ( "all_loadstore_32" ) ;
686- let mut traces = Traces :: from_elf_and_logs ( & elf, & logs, & Default :: default ( ) , & [ ] ) . unwrap ( ) ;
767+ let mut traces =
768+ Traces :: from_elf_and_logs_minimal ( & elf, & logs, & Default :: default ( ) , & [ ] ) . unwrap ( ) ;
687769 assert ! (
688770 prove_and_verify_vm_minimal( & elf, & mut traces) ,
689771 "all_loadstore_32 failed"
@@ -826,7 +908,7 @@ fn test_prove_elfs_test_commit_4() {
826908 ) ;
827909
828910 let mut traces =
829- Traces :: from_elf_and_logs ( & elf, & result. logs , & Default :: default ( ) , & [ ] ) . unwrap ( ) ;
911+ Traces :: from_elf_and_logs_minimal ( & elf, & result. logs , & Default :: default ( ) , & [ ] ) . unwrap ( ) ;
830912 assert_eq ! (
831913 traces. public_output_bytes,
832914 result. return_values. memory_values
@@ -852,7 +934,7 @@ fn test_prove_elfs_test_commit_4_wrong_pages_rejected() {
852934 executor:: vm:: execution:: Executor :: new ( & elf, vec ! [ ] ) . expect ( "Failed to create executor" ) ;
853935 let result = executor. run ( ) . expect ( "Failed to run program" ) ;
854936 let mut traces =
855- Traces :: from_elf_and_logs ( & elf, & result. logs , & Default :: default ( ) , & [ ] ) . unwrap ( ) ;
937+ Traces :: from_elf_and_logs_minimal ( & elf, & result. logs , & Default :: default ( ) , & [ ] ) . unwrap ( ) ;
856938
857939 // Prover uses correct page configs
858940 let table_counts = traces. table_counts ( ) ;
@@ -1553,7 +1635,8 @@ fn test_debug_memory_tokens_sb_sh() {
15531635#[ test]
15541636fn test_deep_stack_passes ( ) {
15551637 let ( elf, logs, _instructions) = run_asm_elf ( "deep_stack" ) ;
1556- let mut traces = Traces :: from_elf_and_logs ( & elf, & logs, & Default :: default ( ) , & [ ] ) . unwrap ( ) ;
1638+ let mut traces =
1639+ Traces :: from_elf_and_logs_minimal ( & elf, & logs, & Default :: default ( ) , & [ ] ) . unwrap ( ) ;
15571640
15581641 assert ! (
15591642 prove_and_verify_vm_minimal( & elf, & mut traces) ,
@@ -1575,7 +1658,7 @@ fn test_deep_stack_runtime_pages_roundtrip() {
15751658 executor:: vm:: execution:: Executor :: new ( & elf, vec ! [ ] ) . expect ( "Failed to create executor" ) ;
15761659 let result = executor. run ( ) . expect ( "Failed to run program" ) ;
15771660 let mut traces =
1578- Traces :: from_elf_and_logs ( & elf, & result. logs , & Default :: default ( ) , & [ ] ) . unwrap ( ) ;
1661+ Traces :: from_elf_and_logs_minimal ( & elf, & result. logs , & Default :: default ( ) , & [ ] ) . unwrap ( ) ;
15791662
15801663 let runtime_page_ranges = traces. runtime_page_ranges ( ) ;
15811664 let table_counts = traces. table_counts ( ) ;
@@ -1635,7 +1718,7 @@ fn test_deep_stack_missing_pages_rejected() {
16351718 executor:: vm:: execution:: Executor :: new ( & elf, vec ! [ ] ) . expect ( "Failed to create executor" ) ;
16361719 let result = executor. run ( ) . expect ( "Failed to run program" ) ;
16371720 let mut traces =
1638- Traces :: from_elf_and_logs ( & elf, & result. logs , & Default :: default ( ) , & [ ] ) . unwrap ( ) ;
1721+ Traces :: from_elf_and_logs_minimal ( & elf, & result. logs , & Default :: default ( ) , & [ ] ) . unwrap ( ) ;
16391722
16401723 // Prover uses correct page configs (auto-detected from MemoryState)
16411724 let table_counts = traces. table_counts ( ) ;
@@ -1686,7 +1769,8 @@ fn test_deep_stack_missing_pages_rejected() {
16861769#[ test]
16871770fn test_heap_alloc_passes ( ) {
16881771 let ( elf, logs, _instructions) = run_asm_elf ( "heap_alloc" ) ;
1689- let mut traces = Traces :: from_elf_and_logs ( & elf, & logs, & Default :: default ( ) , & [ ] ) . unwrap ( ) ;
1772+ let mut traces =
1773+ Traces :: from_elf_and_logs_minimal ( & elf, & logs, & Default :: default ( ) , & [ ] ) . unwrap ( ) ;
16901774
16911775 // Verify runtime_page_ranges includes the heap page
16921776 let ranges = traces. runtime_page_ranges ( ) ;
@@ -1715,7 +1799,7 @@ fn test_heap_alloc_runtime_pages_roundtrip() {
17151799 executor:: vm:: execution:: Executor :: new ( & elf, vec ! [ ] ) . expect ( "Failed to create executor" ) ;
17161800 let result = executor. run ( ) . expect ( "Failed to run program" ) ;
17171801 let mut traces =
1718- Traces :: from_elf_and_logs ( & elf, & result. logs , & Default :: default ( ) , & [ ] ) . unwrap ( ) ;
1802+ Traces :: from_elf_and_logs_minimal ( & elf, & result. logs , & Default :: default ( ) , & [ ] ) . unwrap ( ) ;
17191803
17201804 let runtime_page_ranges = traces. runtime_page_ranges ( ) ;
17211805 let table_counts = traces. table_counts ( ) ;
@@ -1926,11 +2010,9 @@ fn test_crafted_zero_count_proof_must_not_verify() {
19262010#[ test]
19272011fn test_small_max_rows_splits_tables ( ) {
19282012 let elf_bytes = crate :: test_utils:: asm_elf_bytes ( "all_instructions_64" ) ;
1929- let proof_options = ProofOptions :: default_test_options ( ) ;
19302013 let max_rows = crate :: tables:: MaxRowsConfig :: small ( ) ;
19312014
1932- let vm_proof = crate :: prove_with_options ( & elf_bytes, & proof_options, & max_rows)
1933- . expect ( "Prover should succeed with small max_rows" ) ;
2015+ let vm_proof = prove_vm_minimal ( & elf_bytes, & [ ] , & max_rows) ;
19342016
19352017 // With 2^5 max rows and 64+ instructions, tables should have multiple chunks.
19362018 assert ! (
@@ -1939,9 +2021,10 @@ fn test_small_max_rows_splits_tables() {
19392021 vm_proof. table_counts. cpu
19402022 ) ;
19412023
1942- let verified = crate :: verify_with_options ( & vm_proof, & elf_bytes, & proof_options)
1943- . expect ( "Verifier should not error" ) ;
1944- assert ! ( verified, "Proof with small max_rows should verify" ) ;
2024+ assert ! (
2025+ verify_vm_minimal( & vm_proof, & elf_bytes) ,
2026+ "Proof with small max_rows should verify"
2027+ ) ;
19452028}
19462029
19472030// =============================================================================
@@ -2006,8 +2089,11 @@ fn test_verify_rejects_inflated_table_counts() {
20062089#[ test]
20072090fn test_prove_wsuffix_64bit ( ) {
20082091 let elf_bytes = crate :: test_utils:: asm_elf_bytes ( "test_wsuffix_64bit" ) ;
2009- let result = crate :: prove_and_verify ( & elf_bytes) . expect ( "prove_and_verify failed" ) ;
2010- assert ! ( result, "W-suffix 64-bit register test should verify" ) ;
2092+ let vm_proof = prove_vm_minimal ( & elf_bytes, & [ ] , & Default :: default ( ) ) ;
2093+ assert ! (
2094+ verify_vm_minimal( & vm_proof, & elf_bytes) ,
2095+ "W-suffix 64-bit register test should verify"
2096+ ) ;
20112097}
20122098
20132099/// Proves a minimal Rust std program that uses `init_allocator()` and
@@ -2024,9 +2110,9 @@ fn test_prove_allocator_minimal_reproducer() {
20242110 let elf_bytes =
20252111 std:: fs:: read ( workspace_root. join ( "executor/program_artifacts/rust/allocator.elf" ) )
20262112 . expect ( "allocator.elf not found — run `make compile-programs-rust`" ) ;
2027- let proof = crate :: prove ( & elf_bytes) . expect ( "prove should succeed" ) ;
2113+ let proof = prove_vm_minimal ( & elf_bytes, & [ ] , & Default :: default ( ) ) ;
20282114 assert ! (
2029- crate :: verify ( & proof, & elf_bytes) . expect ( "verify should not error" ) ,
2115+ verify_vm_minimal ( & proof, & elf_bytes) ,
20302116 "allocator.elf should verify"
20312117 ) ;
20322118 assert_eq ! ( proof. public_output, b"Hello World" ) ;
@@ -2043,9 +2129,9 @@ fn test_pure_commit_rust() {
20432129 let elf_bytes =
20442130 std:: fs:: read ( workspace_root. join ( "executor/program_artifacts/rust/pure_commit.elf" ) )
20452131 . expect ( "pure_commit.elf not found — run `make compile-programs-rust`" ) ;
2046- let proof = crate :: prove ( & elf_bytes) . expect ( "prove should succeed" ) ;
2132+ let proof = prove_vm_minimal ( & elf_bytes, & [ ] , & Default :: default ( ) ) ;
20472133 assert ! (
2048- crate :: verify ( & proof, & elf_bytes) . expect ( "verify should not error" ) ,
2134+ verify_vm_minimal ( & proof, & elf_bytes) ,
20492135 "pure_commit.elf should verify"
20502136 ) ;
20512137 assert_eq ! ( proof. public_output, vec![ 0xAA , 0xBB , 0xCC , 0xDD ] ) ;
@@ -2068,12 +2154,8 @@ fn test_prove_with_input_empty() {
20682154fn test_prove_private_input_xpage ( ) {
20692155 let elf_bytes = crate :: test_utils:: asm_elf_bytes ( "test_private_input_xpage" ) ;
20702156 let input: Vec < u8 > = ( 0u8 ..16 ) . collect ( ) ;
2071- let proof =
2072- crate :: prove_with_inputs ( & elf_bytes, & input) . expect ( "prove_with_inputs should succeed" ) ;
2073- assert ! (
2074- crate :: verify( & proof, & elf_bytes) . expect( "verify should not error" ) ,
2075- "proof should verify"
2076- ) ;
2157+ let proof = prove_vm_minimal ( & elf_bytes, & input, & Default :: default ( ) ) ;
2158+ assert ! ( verify_vm_minimal( & proof, & elf_bytes) , "proof should verify" ) ;
20772159 assert_eq ! ( proof. public_output, input[ 4 ..12 ] . to_vec( ) ) ;
20782160}
20792161
@@ -2085,11 +2167,8 @@ fn test_prove_private_input_different_values() {
20852167 0xAA , 0xBB , 0xCC , 0xDD , 0xEE , 0xFF , 0x11 , 0x22 , 0x33 , 0x44 , 0x55 , 0x66 , 0x77 , 0x88 , 0x99 ,
20862168 0x00 ,
20872169 ] ;
2088- let proof = crate :: prove_with_inputs ( & elf_bytes, & input) . expect ( "prove" ) ;
2089- assert ! (
2090- crate :: verify( & proof, & elf_bytes) . expect( "verify" ) ,
2091- "proof should verify"
2092- ) ;
2170+ let proof = prove_vm_minimal ( & elf_bytes, & input, & Default :: default ( ) ) ;
2171+ assert ! ( verify_vm_minimal( & proof, & elf_bytes) , "proof should verify" ) ;
20932172 assert_eq ! ( proof. public_output, input[ 4 ..12 ] . to_vec( ) ) ;
20942173}
20952174
@@ -2104,9 +2183,9 @@ fn test_prove_commit_sum() {
21042183 std:: fs:: read ( workspace_root. join ( "executor/program_artifacts/rust/commit_sum.elf" ) )
21052184 . expect ( "commit_sum.elf not found — run `make compile-programs-rust`" ) ;
21062185 let input = & [ 3u8 , 5u8 ] ;
2107- let proof = crate :: prove_with_inputs ( & elf_bytes, input) . expect ( "prove should succeed" ) ;
2186+ let proof = prove_vm_minimal ( & elf_bytes, input, & Default :: default ( ) ) ;
21082187 assert ! (
2109- crate :: verify ( & proof, & elf_bytes) . expect ( "verify should not error" ) ,
2188+ verify_vm_minimal ( & proof, & elf_bytes) ,
21102189 "commit_sum should verify"
21112190 ) ;
21122191 assert_eq ! ( proof. public_output, vec![ 8u8 ] ) ;
@@ -2222,7 +2301,7 @@ fn test_verify_rejects_private_input_with_tampered_public_output() {
22222301 let vm_proof = crate :: prove_with_inputs ( & elf_bytes, & input) . expect ( "prove should succeed" ) ;
22232302
22242303 assert ! (
2225- crate :: verify( & vm_proof, & elf_bytes) . expect( "verify" ) ,
2304+ crate :: verify( & vm_proof, & elf_bytes) . expect( "verify should not error " ) ,
22262305 "Baseline must verify"
22272306 ) ;
22282307
@@ -2271,8 +2350,11 @@ fn test_proof_does_not_contain_private_input_field() {
22712350#[ test]
22722351fn test_addiw_neg_immediate ( ) {
22732352 let elf_bytes = crate :: test_utils:: asm_elf_bytes ( "test_addiw_neg" ) ;
2274- let result = crate :: prove_and_verify ( & elf_bytes) . expect ( "prove_and_verify failed" ) ;
2275- assert ! ( result, "addiw with negative immediate should verify" ) ;
2353+ let proof = prove_vm_minimal ( & elf_bytes, & [ ] , & Default :: default ( ) ) ;
2354+ assert ! (
2355+ verify_vm_minimal( & proof, & elf_bytes) ,
2356+ "addiw with negative immediate should verify"
2357+ ) ;
22762358}
22772359
22782360/// Regression test: both main and aux field element counts must be nonzero for any real ELF.
0 commit comments