diff --git a/barretenberg/cpp/src/barretenberg/avm_fuzzer/mutations/tx_data.cpp b/barretenberg/cpp/src/barretenberg/avm_fuzzer/mutations/tx_data.cpp index e5b684859e37..5455e0ddf2a8 100644 --- a/barretenberg/cpp/src/barretenberg/avm_fuzzer/mutations/tx_data.cpp +++ b/barretenberg/cpp/src/barretenberg/avm_fuzzer/mutations/tx_data.cpp @@ -5,6 +5,7 @@ #include "barretenberg/avm_fuzzer/mutations/basic_types/vector.hpp" #include "barretenberg/avm_fuzzer/mutations/fuzzer_data.hpp" #include "barretenberg/avm_fuzzer/mutations/instructions/instruction_block.hpp" +#include "barretenberg/avm_fuzzer/mutations/tx_types/accumulated_data.hpp" #include "barretenberg/avm_fuzzer/mutations/tx_types/public_call_request.hpp" #include "barretenberg/vm2/common/avm_io.hpp" #include "barretenberg/vm2/common/aztec_constants.hpp" @@ -91,6 +92,16 @@ void mutate_tx(Tx& tx, std::vector& contract_addresses, std::mt199 fuzz_info("Mutating teardown enqueued call"); mutate_teardown(tx.teardown_enqueued_call, contract_addresses, rng); break; + case TxMutationOptions::NonRevertibleData: + // Mutate non-revertible accumulated data + fuzz_info("Mutating non-revertible accumulated data"); + mutate_non_revertible_accumulated_data(tx.non_revertible_accumulated_data, rng); + break; + case TxMutationOptions::RevertibleData: + // Mutate revertible accumulated data + fuzz_info("Mutating revertible accumulated data"); + mutate_revertible_accumulated_data(tx.revertible_accumulated_data, rng); + break; // case 2: // // Mutate gas_settings @@ -103,32 +114,6 @@ void mutate_tx(Tx& tx, std::vector& contract_addresses, std::mt199 // case 4: // // Mutate Deployment data // break; - // case 5: - // // Mutate non-revertible accumulated data - // // fixme: maybe don't change all stuff - // mutate_ff_vec(tx.non_revertible_accumulated_data.note_hashes, rng, MAX_NOTE_HASHES_PER_TX); - // mutate_ff_vec(tx.non_revertible_accumulated_data.nullifiers, rng, MAX_NULLIFIERS_PER_TX); - // mutate_vec(tx.non_revertible_accumulated_data.l2_to_l1_messages, - // rng, - // mutate_l2_to_l1_msg, - // generate_l2_to_l1_msg, - // BASIC_VEC_MUTATION_CONFIGURATION); - // if (tx.non_revertible_accumulated_data.nullifiers.empty()) { - // // Need to ensure the "tx nullifier" exists - // tx.non_revertible_accumulated_data.nullifiers.push_back(generate_random_field(rng)); - // } - // break; - // case 6: - // // Mutate revertible accumulated data - // mutate_ff_vec(tx.revertible_accumulated_data.note_hashes, rng, MAX_NOTE_HASHES_PER_TX); - // mutate_ff_vec(tx.revertible_accumulated_data.nullifiers, rng, MAX_NULLIFIERS_PER_TX); - // mutate_vec(tx.revertible_accumulated_data.l2_to_l1_messages, - // rng, - // mutate_l2_to_l1_msg, - // generate_l2_to_l1_msg, - // BASIC_VEC_MUTATION_CONFIGURATION); - // break; - // break; // case 8: // // Mutate gas_used_by_private // break; @@ -213,34 +198,6 @@ void mutate_gas_fees(GasFees& fees, std::mt19937_64& rng) } } -void mutate_l2_to_l1_msg(ScopedL2ToL1Message& msg, std::mt19937_64& rng) -{ - auto choice = std::uniform_int_distribution(0, 2)(rng); - - switch (choice) { - case 0: - // Mutate recipient - msg.message.recipient = generate_random_field(rng); - break; - case 1: - // Mutate content - msg.message.content = generate_random_field(rng); - break; - case 2: - // Mutate contract_address - msg.contract_address = generate_random_field(rng); - break; - } -} - -ScopedL2ToL1Message generate_l2_to_l1_msg(std::mt19937_64& rng) -{ - return ScopedL2ToL1Message{ - .message = L2ToL1Message{ .recipient = generate_random_field(rng), .content = generate_random_field(rng) }, - .contract_address = generate_random_field(rng), - }; -} - void mutate_fuzzer_data_vec(const FuzzerContext& context, std::vector& enqueued_calls, std::mt19937_64& rng, diff --git a/barretenberg/cpp/src/barretenberg/avm_fuzzer/mutations/tx_data.hpp b/barretenberg/cpp/src/barretenberg/avm_fuzzer/mutations/tx_data.hpp index b794b922e605..3bc6d10d6534 100644 --- a/barretenberg/cpp/src/barretenberg/avm_fuzzer/mutations/tx_data.hpp +++ b/barretenberg/cpp/src/barretenberg/avm_fuzzer/mutations/tx_data.hpp @@ -13,14 +13,18 @@ enum class TxMutationOptions { SetupEnqueuedCalls, AppLogicEnqueuedCalls, TearDownEnqueuedCall, + NonRevertibleData, + RevertibleData, }; -using TxMutationConfig = WeightedSelectionConfig; +using TxMutationConfig = WeightedSelectionConfig; constexpr TxMutationConfig TX_MUTATION_CONFIGURATION = TxMutationConfig({ { TxMutationOptions::SetupEnqueuedCalls, 30 }, { TxMutationOptions::AppLogicEnqueuedCalls, 30 }, { TxMutationOptions::TearDownEnqueuedCall, 10 }, + { TxMutationOptions::NonRevertibleData, 15 }, + { TxMutationOptions::RevertibleData, 15 }, }); namespace bb::avm2::fuzzer { @@ -36,10 +40,6 @@ void mutate_gas(Gas& gas, std::mt19937_64& rng); // GasFees mutation void mutate_gas_fees(GasFees& fees, std::mt19937_64& rng); -// L2ToL1Msg vector mutation -void mutate_l2_to_l1_msg(ScopedL2ToL1Message& vec, std::mt19937_64& rng); -ScopedL2ToL1Message generate_l2_to_l1_msg(std::mt19937_64& rng); - void mutate_fuzzer_data_vec(const FuzzerContext& context, std::vector& enqueued_calls, std::mt19937_64& rng, diff --git a/barretenberg/cpp/src/barretenberg/avm_fuzzer/mutations/tx_types/accumulated_data.cpp b/barretenberg/cpp/src/barretenberg/avm_fuzzer/mutations/tx_types/accumulated_data.cpp new file mode 100644 index 000000000000..02cdb70c335f --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/avm_fuzzer/mutations/tx_types/accumulated_data.cpp @@ -0,0 +1,187 @@ +#include "barretenberg/avm_fuzzer/mutations/tx_types/accumulated_data.hpp" + +#include "barretenberg/avm_fuzzer/fuzz_lib/constants.hpp" +#include "barretenberg/avm_fuzzer/mutations/basic_types/field.hpp" +#include "barretenberg/avm_fuzzer/mutations/basic_types/vector.hpp" +#include "barretenberg/avm_fuzzer/mutations/configuration.hpp" +#include "barretenberg/vm2/common/avm_io.hpp" + +using bb::avm2::AztecAddress; +using bb::avm2::FF; + +namespace { + +// Generate a random note hash +FF generate_note_hash(std::mt19937_64& rng) +{ + return generate_random_field(rng); +} + +void mutate_note_hash(FF& note_hash, std::mt19937_64& rng) +{ + mutate_field(note_hash, rng, BASIC_FIELD_MUTATION_CONFIGURATION); +} + +// Generate a random nullifier +FF generate_nullifier(std::mt19937_64& rng) +{ + return generate_random_field(rng); +} + +void mutate_nullifier(FF& nullifier, std::mt19937_64& rng) +{ + mutate_field(nullifier, rng, BASIC_FIELD_MUTATION_CONFIGURATION); +} + +// Generate a random L2 to L1 message +ScopedL2ToL1Message generate_l2_to_l1_message(std::mt19937_64& rng) +{ + return ScopedL2ToL1Message{ + .message = L2ToL1Message{ .recipient = generate_random_field(rng), .content = generate_random_field(rng) }, + .contract_address = generate_random_field(rng), + }; +} + +void mutate_l2_to_l1_msg(ScopedL2ToL1Message& msg, std::mt19937_64& rng) +{ + auto choice = std::uniform_int_distribution(0, 2)(rng); + + switch (choice) { + case 0: + // Mutate recipient + msg.message.recipient = generate_random_field(rng); + break; + case 1: + // Mutate content + msg.message.content = generate_random_field(rng); + break; + case 2: + // Mutate contract_address + msg.contract_address = generate_random_field(rng); + break; + default: + break; + } +} + +AccumulatedData generate_accumulated_data(std::mt19937_64& rng) +{ + // When we generate new accumulated data we can simply generate a small number of entries + // We test the limits during mutation + std::vector note_hashes; + size_t num_note_hashes = std::uniform_int_distribution(0, 4)(rng); + note_hashes.reserve(num_note_hashes); + for (size_t i = 0; i < num_note_hashes; i++) { + note_hashes.push_back(generate_note_hash(rng)); + } + std::vector nullifiers; + size_t num_nullifiers = std::uniform_int_distribution(0, 4)(rng); + nullifiers.reserve(num_nullifiers); + for (size_t i = 0; i < num_nullifiers; i++) { + nullifiers.push_back(generate_nullifier(rng)); + } + std::vector l2_to_l1_messages; + size_t num_messages = std::uniform_int_distribution(0, 4)(rng); + l2_to_l1_messages.reserve(num_messages); + for (size_t i = 0; i < num_messages; i++) { + l2_to_l1_messages.push_back(generate_l2_to_l1_message(rng)); + } + + return AccumulatedData{ + .note_hashes = note_hashes, + .nullifiers = nullifiers, + .l2_to_l1_messages = l2_to_l1_messages, + }; +} + +void mutate_accumulated_data(AccumulatedData& input, std::mt19937_64& rng) +{ + using namespace bb::avm2::fuzzer; + // We only really care about the existence of note hashes, nullifiers, and L2 to L1 messages + // or if these values end up triggering limit errors during execution. + auto choice = ACCUMULATED_DATA_MUTATION_CONFIGURATION.select(rng); + switch (choice) { + case AccumulatedDataMutationOptions::NoteHashes: + mutate_vec_with_limit(input.note_hashes, + rng, + mutate_note_hash, + generate_note_hash, + BASIC_VEC_MUTATION_CONFIGURATION, + MAX_NOTE_HASHES_PER_TX); + break; + case AccumulatedDataMutationOptions::NoteHashesLimit: { + size_t original_size = input.note_hashes.size(); + input.note_hashes.resize(MAX_NOTE_HASHES_PER_TX); + for (size_t i = original_size; i < MAX_NOTE_HASHES_PER_TX; i++) { + input.note_hashes[i] = generate_note_hash(rng); + } + break; + } + case AccumulatedDataMutationOptions::Nullifiers: + mutate_vec_with_limit(input.nullifiers, + rng, + mutate_nullifier, + generate_nullifier, + BASIC_VEC_MUTATION_CONFIGURATION, + MAX_NULLIFIERS_PER_TX); + break; + case AccumulatedDataMutationOptions::NullifiersLimit: { + size_t original_size = input.nullifiers.size(); + input.nullifiers.resize(MAX_NULLIFIERS_PER_TX); + for (size_t i = original_size; i < MAX_NULLIFIERS_PER_TX; i++) { + input.nullifiers[i] = generate_nullifier(rng); + } + break; + } + case AccumulatedDataMutationOptions::L2ToL1Messages: + mutate_vec_with_limit(input.l2_to_l1_messages, + rng, + mutate_l2_to_l1_msg, + generate_l2_to_l1_message, + BASIC_VEC_MUTATION_CONFIGURATION, + MAX_L2_TO_L1_MSGS_PER_TX); + break; + case AccumulatedDataMutationOptions::L2ToL1MessagesLimit: { + size_t original_size = input.l2_to_l1_messages.size(); + input.l2_to_l1_messages.resize(MAX_L2_TO_L1_MSGS_PER_TX); + for (size_t i = original_size; i < MAX_L2_TO_L1_MSGS_PER_TX; i++) { + input.l2_to_l1_messages[i] = generate_l2_to_l1_message(rng); + } + break; + } + } +} + +} // namespace + +namespace bb::avm2::fuzzer { + +AccumulatedData generate_non_revertible_accumulated_data(std::mt19937_64& rng) +{ + AccumulatedData data = generate_accumulated_data(rng); + if (data.nullifiers.empty()) { + // Need to ensure the "tx nullifier" exists + data.nullifiers.push_back(generate_nullifier(rng)); + } + return data; +} +void mutate_non_revertible_accumulated_data(AccumulatedData& data, std::mt19937_64& rng) +{ + mutate_accumulated_data(data, rng); + if (data.nullifiers.empty()) { + // Need to ensure the "tx nullifier" exists + data.nullifiers.push_back(generate_nullifier(rng)); + } +} + +AccumulatedData generate_revertible_accumulated_data(std::mt19937_64& rng) +{ + return generate_accumulated_data(rng); +} + +void mutate_revertible_accumulated_data(AccumulatedData& data, std::mt19937_64& rng) +{ + mutate_accumulated_data(data, rng); +}; + +} // namespace bb::avm2::fuzzer diff --git a/barretenberg/cpp/src/barretenberg/avm_fuzzer/mutations/tx_types/accumulated_data.hpp b/barretenberg/cpp/src/barretenberg/avm_fuzzer/mutations/tx_types/accumulated_data.hpp new file mode 100644 index 000000000000..0cc65ab7b18e --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/avm_fuzzer/mutations/tx_types/accumulated_data.hpp @@ -0,0 +1,51 @@ +#pragma once + +#include + +#include "barretenberg/avm_fuzzer/common/weighted_selection.hpp" +#include "barretenberg/avm_fuzzer/mutations/configuration.hpp" +#include "barretenberg/vm2/common/avm_io.hpp" + +namespace bb::avm2::fuzzer { + +enum class AccumulatedDataMutationOptions : uint8_t { + NoteHashes, + NoteHashesLimit, + Nullifiers, + NullifiersLimit, + L2ToL1Messages, + L2ToL1MessagesLimit, +}; + +using AccumulatedDataMutationConfig = WeightedSelectionConfig; + +constexpr AccumulatedDataMutationConfig ACCUMULATED_DATA_MUTATION_CONFIGURATION = AccumulatedDataMutationConfig({ + { AccumulatedDataMutationOptions::NoteHashes, 20 }, + { AccumulatedDataMutationOptions::NoteHashesLimit, 1 }, + { AccumulatedDataMutationOptions::Nullifiers, 20 }, + { AccumulatedDataMutationOptions::NullifiersLimit, 1 }, + { AccumulatedDataMutationOptions::L2ToL1Messages, 20 }, + { AccumulatedDataMutationOptions::L2ToL1MessagesLimit, 1 }, +}); + +template +void mutate_vec_with_limit(std::vector& vec, + std::mt19937_64& rng, + std::function mutate_element_function, + std::function generate_random_element_function, + const VecMutationConfig& config, + size_t vec_limit) +{ + mutate_vec(vec, rng, mutate_element_function, generate_random_element_function, config); + if (vec.size() > vec_limit) { + vec.resize(vec_limit); + } +} + +AccumulatedData generate_non_revertible_accumulated_data(std::mt19937_64& rng); +void mutate_non_revertible_accumulated_data(AccumulatedData& data, std::mt19937_64& rng); + +AccumulatedData generate_revertible_accumulated_data(std::mt19937_64& rng); +void mutate_revertible_accumulated_data(AccumulatedData& data, std::mt19937_64& rng); + +} // namespace bb::avm2::fuzzer