@@ -3,11 +3,9 @@ use alloc::vec::Vec;
33use std:: collections:: BTreeMap ;
44
55use anyhow:: Context ;
6- use miden_core_lib:: CoreLibrary ;
7- use miden_processor:: { DefaultHost , ExecutionOptions , FastProcessor } ;
8- use miden_protocol:: batch:: { BatchId , BatchKernel , ProposedBatch } ;
6+ use miden_protocol:: batch:: { BatchKernel , ProposedBatch } ;
97use miden_protocol:: block:: BlockNumber ;
10- use miden_protocol:: vm:: { AdviceInputs , StackInputs , StackOutputs } ;
8+ use miden_protocol:: vm:: AdviceInputs ;
119use miden_protocol:: { Felt , Hasher , Word } ;
1210use miden_tx_batch_prover:: { BatchExecutor , LocalBatchProver } ;
1311
@@ -83,30 +81,24 @@ fn expected_input_notes_commitment(batch: &ProposedBatch) -> Word {
8381 }
8482}
8583
86- // EXECUTION HELPERS
84+ // TAMPERING HELPERS
8785// ================================================================================================
8886
89- /// Runs the batch kernel directly over the given inputs, returning its output stack.
90- ///
91- /// Used by the tampering tests, which corrupt the advice inputs before execution. `BatchExecutor`
92- /// builds the advice internally from a (valid) `ProposedBatch` and offers no injection point, so it
93- /// cannot exercise the kernel's rejection paths. This mirrors how the transaction-kernel tests
94- /// inject tampered advice and run kernel code directly (see `tx_context.execute_code` with
95- /// `extend_advice_inputs` in `test_prologue.rs`).
96- fn run_kernel (
97- stack_inputs : StackInputs ,
98- advice_inputs : AdviceInputs ,
99- ) -> Result < StackOutputs , miden_processor:: ExecutionError > {
100- let mut host = DefaultHost :: default ( ) ;
101- host. load_library ( CoreLibrary :: default ( ) . mast_forest ( ) )
102- . expect ( "loading the core library into the test host should succeed" ) ;
103-
104- let processor =
105- FastProcessor :: new_with_options ( stack_inputs, advice_inputs, ExecutionOptions :: default ( ) )
106- . expect ( "failed to create processor" )
107- . with_debugging ( true ) ;
108- let output = processor. execute_sync ( & BatchKernel :: main ( ) , & mut host) ?;
109- Ok ( output. stack )
87+ /// Builds an advice-inputs override that corrupts the advice-map entry stored under `key`, so the
88+ /// kernel's hash check against `key` fails. Fed to [`BatchExecutor::extend_advice_inputs`] to drive
89+ /// the kernel's rejection paths through the normal executor (mirroring how the transaction-kernel
90+ /// tests inject tampered advice via `extend_advice_inputs`; see `test_prologue.rs`).
91+ fn tampered_advice_for ( batch : & ProposedBatch , key : Word ) -> AdviceInputs {
92+ let ( _, advice_inputs) = BatchKernel :: prepare_inputs ( batch) ;
93+ let mut tampered: Vec < Felt > = advice_inputs
94+ . map
95+ . get ( & key)
96+ . expect ( "advice-map entry for key" )
97+ . iter ( )
98+ . copied ( )
99+ . collect ( ) ;
100+ tampered[ 0 ] += Felt :: from ( 1u32 ) ;
101+ AdviceInputs :: default ( ) . with_map ( [ ( key, tampered) ] )
110102}
111103
112104// HAPPY PATH
@@ -148,63 +140,51 @@ fn batch_executor_then_prover_produces_proven_batch() -> anyhow::Result<()> {
148140
149141// NEGATIVE TESTS
150142// ================================================================================================
143+ //
144+ // Each test injects a tampered advice-map entry through `BatchExecutor::extend_advice_inputs` and
145+ // asserts the kernel aborts. The executor builds consistent advice from the (valid) `ProposedBatch`
146+ // and the override then corrupts a single layer's entry, breaking that layer's hash check.
151147
152- /// Corrupting `BATCH_ID` on the input stack makes Layer 1 unloadable from the advice map, so the
153- /// kernel must abort.
148+ /// Tampering the `BATCH_ID` -> `(tx_id, account_id)` tuples breaks the Layer 1 hash check.
154149#[ test]
155- fn batch_kernel_rejects_wrong_batch_id ( ) -> anyhow:: Result < ( ) > {
150+ fn batch_kernel_rejects_tampered_layer_1 ( ) -> anyhow:: Result < ( ) > {
156151 let mut setup = setup_chain ( ) ;
157152 let batch = two_tx_batch ( & mut setup) ?;
158153
159- let block_commitment = batch. reference_block_header ( ) . commitment ( ) ;
160- // A BatchId over a one-transaction subset differs from the real (two-tx) batch id, so the
161- // kernel cannot find its Layer 1 tuples in the advice map.
162- let bogus_tx = & batch. transactions ( ) [ 0 ] ;
163- let bogus_batch_id = BatchId :: from_ids ( [ ( bogus_tx. id ( ) , bogus_tx. account_id ( ) ) ] ) ;
164- let stack_inputs = BatchKernel :: build_input_stack ( block_commitment, bogus_batch_id) ;
165- let ( _, advice_inputs) = BatchKernel :: prepare_inputs ( & batch) ;
154+ let override_advice = tampered_advice_for ( & batch, batch. id ( ) . as_word ( ) ) ;
166155
167- run_kernel ( stack_inputs, advice_inputs) . expect_err ( "kernel must abort on an unknown BATCH_ID" ) ;
156+ let result = BatchExecutor :: new ( ) . extend_advice_inputs ( override_advice) . execute ( batch) ;
157+ assert ! ( result. is_err( ) , "kernel must abort on a tampered transaction list" ) ;
168158
169159 Ok ( ( ) )
170160}
171161
172- /// Tampering a verified `tx_id`'s Layer 2 advice-map entry breaks the per-tx header hash check.
162+ /// Tampering a verified `tx_id`'s header data breaks the Layer 2 hash check.
173163#[ test]
174164fn batch_kernel_rejects_tampered_layer_2 ( ) -> anyhow:: Result < ( ) > {
175165 let mut setup = setup_chain ( ) ;
176166 let batch = two_tx_batch ( & mut setup) ?;
177167
178- let ( stack_inputs, mut advice_inputs) = BatchKernel :: prepare_inputs ( & batch) ;
179-
180168 let tx0_id = batch. transactions ( ) [ 0 ] . id ( ) . as_word ( ) ;
181- let entry = advice_inputs. map . get ( & tx0_id) . expect ( "tx0 layer 2 entry" ) ;
182- let mut tampered: Vec < Felt > = entry. iter ( ) . copied ( ) . collect ( ) ;
183- tampered[ 0 ] += Felt :: from ( 1u32 ) ;
184- advice_inputs. map . extend ( [ ( tx0_id, tampered) ] ) ;
169+ let override_advice = tampered_advice_for ( & batch, tx0_id) ;
185170
186- run_kernel ( stack_inputs , advice_inputs )
187- . expect_err ( "kernel must abort on a tampered transaction header" ) ;
171+ let result = BatchExecutor :: new ( ) . extend_advice_inputs ( override_advice ) . execute ( batch ) ;
172+ assert ! ( result . is_err ( ) , "kernel must abort on a tampered transaction header" ) ;
188173
189174 Ok ( ( ) )
190175}
191176
192- /// Tampering the per-tx input-notes Layer 3 entry breaks the input-note hash check.
177+ /// Tampering a transaction's input-notes data breaks the Layer 3 ( input-notes commitment) check.
193178#[ test]
194179fn batch_kernel_rejects_tampered_input_notes ( ) -> anyhow:: Result < ( ) > {
195180 let mut setup = setup_chain ( ) ;
196181 let batch = two_tx_batch ( & mut setup) ?;
197182
198- let ( stack_inputs, mut advice_inputs) = BatchKernel :: prepare_inputs ( & batch) ;
199-
200183 let key = batch. transactions ( ) [ 0 ] . input_notes ( ) . commitment ( ) ;
201- let entry = advice_inputs. map . get ( & key) . expect ( "layer 3 entry" ) ;
202- let mut tampered: Vec < Felt > = entry. iter ( ) . copied ( ) . collect ( ) ;
203- tampered[ 0 ] += Felt :: from ( 1u32 ) ;
204- advice_inputs. map . extend ( [ ( key, tampered) ] ) ;
184+ let override_advice = tampered_advice_for ( & batch, key) ;
205185
206- run_kernel ( stack_inputs , advice_inputs )
207- . expect_err ( "kernel must abort on tampered input notes data" ) ;
186+ let result = BatchExecutor :: new ( ) . extend_advice_inputs ( override_advice ) . execute ( batch ) ;
187+ assert ! ( result . is_err ( ) , "kernel must abort on tampered input- notes data" ) ;
208188
209189 Ok ( ( ) )
210190}
0 commit comments