11#include " barretenberg/avm_fuzzer/mutations/tx_data.hpp"
2+
23#include " barretenberg/avm_fuzzer/fuzz_lib/constants.hpp"
34#include " barretenberg/avm_fuzzer/mutations/basic_types/field.hpp"
45#include " barretenberg/avm_fuzzer/mutations/basic_types/vector.hpp"
56#include " barretenberg/avm_fuzzer/mutations/fuzzer_data.hpp"
67#include " barretenberg/avm_fuzzer/mutations/instructions/instruction_block.hpp"
8+ #include " barretenberg/avm_fuzzer/mutations/tx_types/public_call_request.hpp"
9+ #include " barretenberg/vm2/common/avm_io.hpp"
710#include " barretenberg/vm2/common/aztec_constants.hpp"
811#include " barretenberg/vm2/common/aztec_types.hpp"
912#include " barretenberg/vm2/common/tagged_value.hpp"
1013#include " barretenberg/vm2/simulation/lib/contract_crypto.hpp"
1114
15+ #include < optional>
1216#include < random>
1317
18+ namespace {
19+
20+ void mutate_enqueued_calls (std::vector<PublicCallRequestWithCalldata>& enqueued_calls,
21+ std::vector<AztecAddress>& contract_addresses,
22+ std::mt19937_64& rng)
23+ {
24+ auto mutate_fn = [&](PublicCallRequestWithCalldata& call, std::mt19937_64& rng) {
25+ bb::avm2::fuzzer::mutate_public_call_request (call, contract_addresses, rng);
26+ };
27+
28+ auto gen_fn = [&](std::mt19937_64& rng) {
29+ return bb::avm2::fuzzer::generate_public_call_request (contract_addresses, rng);
30+ };
31+
32+ mutate_vec<PublicCallRequestWithCalldata>(enqueued_calls, rng, mutate_fn, gen_fn, BASIC_VEC_MUTATION_CONFIGURATION);
33+ };
34+
35+ void mutate_teardown (std::optional<PublicCallRequestWithCalldata>& teardown_call,
36+ std::vector<AztecAddress>& contract_addresses,
37+ std::mt19937_64& rng)
38+ {
39+ if (!teardown_call.has_value ()) {
40+ // Nothing to mutate, generate a new one
41+ teardown_call = bb::avm2::fuzzer::generate_public_call_request (contract_addresses, rng);
42+ return ;
43+ }
44+
45+ // If we already have a teardown call, there's a 1 in 10 chance we discard it
46+ bool discard = std::uniform_int_distribution<int >(0 , 9 )(rng) == 0 ;
47+ if (discard) {
48+ fuzz_info (" Discarding teardown enqueued call" );
49+ teardown_call = PublicCallRequestWithCalldata{};
50+ } else {
51+ // Mutate existing teardown call
52+ bb::avm2::fuzzer::mutate_public_call_request (teardown_call.value (), contract_addresses, rng);
53+ }
54+ }
55+
56+ } // namespace
57+
1458namespace bb ::avm2::fuzzer {
1559
1660// Gas bounds for mutation
@@ -29,32 +73,25 @@ constexpr uint32_t AVM_MAX_PROCESSABLE_DA_GAS = (MAX_NOTE_HASHES_PER_TX * AVM_EM
2973
3074void mutate_tx (Tx& tx, std::vector<AztecAddress>& contract_addresses, std::mt19937_64& rng)
3175{
32- auto choice = std::uniform_int_distribution< uint8_t >( 0 , 1 ) (rng);
76+ auto choice = TX_MUTATION_CONFIGURATION. select (rng);
3377
3478 switch (choice) {
35- case 0 :
79+ case TxMutationOptions::SetupEnqueuedCalls :
3680 // Mutate setup enqueued calls
3781 fuzz_info (" Mutating setup enqueued calls: " , tx.setup_enqueued_calls .size ());
38- mutate_vec<PublicCallRequestWithCalldata>(
39- tx.setup_enqueued_calls ,
40- rng,
41- [&](PublicCallRequestWithCalldata& call, std::mt19937_64& rng) {
42- mutate_public_call_request (call, contract_addresses, rng);
43- },
44- [&](std::mt19937_64& rng) { return generate_public_call_request (contract_addresses, rng); },
45- BASIC_VEC_MUTATION_CONFIGURATION);
82+ mutate_enqueued_calls (tx.setup_enqueued_calls , contract_addresses, rng);
4683 break ;
47- case 1 :
84+ case TxMutationOptions::AppLogicEnqueuedCalls :
4885 // Mutate app logic enqueued calls
4986 fuzz_info (" Mutating app logic enqueued calls: " , tx.app_logic_enqueued_calls .size ());
50- mutate_vec<PublicCallRequestWithCalldata>(
51- tx. app_logic_enqueued_calls ,
52- rng,
53- [&](PublicCallRequestWithCalldata& call, std::mt19937_64& rng) {
54- mutate_public_call_request ( call, contract_addresses, rng );
55- },
56- [&](std::mt19937_64& rng) { return generate_public_call_request (contract_addresses, rng); },
57- BASIC_VEC_MUTATION_CONFIGURATION);
87+ mutate_enqueued_calls (tx. app_logic_enqueued_calls , contract_addresses, rng);
88+ break ;
89+ case TxMutationOptions::TearDownEnqueuedCall:
90+ // Mutate teardown enqueued call
91+ fuzz_info ( " Mutating teardown enqueued call" );
92+ mutate_teardown (tx. teardown_enqueued_call , contract_addresses, rng);
93+ break ;
94+
5895 // case 2:
5996 // // Mutate gas_settings
6097 // mutate_gas_settings(tx.gas_settings, rng);
@@ -92,10 +129,6 @@ void mutate_tx(Tx& tx, std::vector<AztecAddress>& contract_addresses, std::mt199
92129 // BASIC_VEC_MUTATION_CONFIGURATION);
93130 // break;
94131 // break;
95- // case 7:
96- // // Mutate teardown enqueued call
97- //
98- // break;
99132 // case 8:
100133 // // Mutate gas_used_by_private
101134 // break;
@@ -180,20 +213,6 @@ void mutate_gas_fees(GasFees& fees, std::mt19937_64& rng)
180213 }
181214}
182215
183- void mutate_ff_vec (std::vector<FF>& vec, std::mt19937_64& rng, size_t max_size)
184- {
185- mutate_vec<FF>(
186- vec,
187- rng,
188- [](bb::avm2::FF& value, std::mt19937_64& rng) { mutate_field (value, rng, BASIC_FIELD_MUTATION_CONFIGURATION); },
189- generate_random_field,
190- BASIC_VEC_MUTATION_CONFIGURATION);
191-
192- if (vec.size () > max_size) {
193- vec.resize (max_size);
194- }
195- }
196-
197216void mutate_l2_to_l1_msg (ScopedL2ToL1Message& msg, std::mt19937_64& rng)
198217{
199218 auto choice = std::uniform_int_distribution<uint8_t >(0 , 2 )(rng);
@@ -222,26 +241,6 @@ ScopedL2ToL1Message generate_l2_to_l1_msg(std::mt19937_64& rng)
222241 };
223242}
224243
225- void mutate_bool_vec (std::vector<bool >& vec, size_t target_size, std::mt19937_64& rng)
226- {
227- // Resize to match target size
228- while (vec.size () < target_size) {
229- vec.push_back (std::uniform_int_distribution<uint8_t >(0 , 1 )(rng) == 1 );
230- }
231- while (vec.size () > target_size) {
232- vec.pop_back ();
233- }
234-
235- // Flip a random bool with some probability
236- if (!vec.empty ()) {
237- auto flip_prob = std::uniform_int_distribution<uint8_t >(0 , 4 )(rng);
238- if (flip_prob == 0 ) {
239- auto idx = std::uniform_int_distribution<size_t >(0 , vec.size () - 1 )(rng);
240- vec[idx] = !vec[idx];
241- }
242- }
243- }
244-
245244void mutate_fuzzer_data_vec (std::vector<FuzzerData>& enqueued_calls, std::mt19937_64& rng, size_t max_size)
246245{
247246 auto choice = std::uniform_int_distribution<uint8_t >(0 , 1 )(rng);
@@ -278,73 +277,4 @@ void mutate_fuzzer_data_vec(std::vector<FuzzerData>& enqueued_calls, std::mt1993
278277 }
279278}
280279
281- void mutate_public_call_request ([[maybe_unused]] PublicCallRequestWithCalldata& request,
282- [[maybe_unused]] std::vector<AztecAddress>& contract_addresses,
283- [[maybe_unused]] std::mt19937_64& rng)
284- {
285- if (contract_addresses.empty ()) {
286- return ; // Nothing to mutate to
287- }
288- // fixme(ilyas): this should be weighted since stuff like mutate calldata hash is fail-early
289- auto choice = std::uniform_int_distribution<uint8_t >(0 , 0 )(rng);
290- //
291- switch (choice) {
292- case 0 :
293- // Mutate contract_address
294- // This is likely to cause immediate failure, needs to be weighted appropriately
295- auto contract_address_choice = std::uniform_int_distribution<size_t >(0 , contract_addresses.size () - 1 )(rng);
296- auto contract_address = contract_addresses[contract_address_choice];
297- request.request .contract_address = contract_address;
298- break ;
299- // case 1:
300- // // Mutate msg_sender
301- // request.request.msg_sender = generate_random_field(rng);
302- // break;
303- // case 2: {
304- // // Mutate is_static_call
305- // request.request.is_static_call = !request.request.is_static_call;
306- // break;
307- // }
308- // case 3:
309- // // Mutate calldata_hash - the intention here is to fail the hash check
310- // request.request.calldata_hash = generate_random_field(rng);
311- // break;
312- // case 4:
313- // // Mutate calldata
314- // mutate_ff_vec(request.calldata, rng, 256);
315- // // fixme: recompute calldata_hash when we start doing tracegen versions
316- // // request.calldata_hash = compute_calldata_hash(request.calldata);
317- // break;
318- }
319- }
320-
321- PublicCallRequestWithCalldata generate_public_call_request (std::vector<AztecAddress>& contract_addresses,
322- std::mt19937_64& rng)
323- {
324- fuzz_info (" Generating new public call request" );
325- // Generate random calldata
326- size_t calldata_size = std::uniform_int_distribution<size_t >(0 , 256 )(rng);
327- std::vector<FF> calldata{};
328- for (size_t i = 0 ; i < calldata_size; ++i) {
329- calldata.push_back (generate_random_field (rng));
330- }
331-
332- auto contract_address =
333- contract_addresses.empty ()
334- ? generate_random_field (rng)
335- : contract_addresses[std::uniform_int_distribution<size_t >(0 , contract_addresses.size () - 1 )(rng)];
336- fuzz_info (" Using contract address: " , contract_address);
337- FF calldata_hash = simulation::compute_calldata_hash (calldata);
338- return PublicCallRequestWithCalldata{
339- .request =
340- PublicCallRequest{
341- .msg_sender = generate_random_field (rng),
342- .contract_address = contract_address,
343- .is_static_call = (std::uniform_int_distribution<uint8_t >(0 , 1 )(rng) == 1 ),
344- .calldata_hash = calldata_hash,
345- },
346- .calldata = calldata,
347- };
348- }
349-
350280} // namespace bb::avm2::fuzzer
0 commit comments