Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions barretenberg/cpp/src/barretenberg/avm_fuzzer/fuzzer_lib.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include "barretenberg/avm_fuzzer/fuzzer_comparison_helper.hpp"
#include "barretenberg/avm_fuzzer/mutations/fuzzer_data.hpp"
#include "barretenberg/avm_fuzzer/mutations/tx_data.hpp"
#include "barretenberg/avm_fuzzer/mutations/tx_types/gas.hpp"
#include "barretenberg/common/log.hpp"
#include "barretenberg/vm2/avm_api.hpp"
#include "barretenberg/vm2/common/avm_io.hpp"
Expand Down Expand Up @@ -333,6 +334,12 @@ size_t mutate_tx_data(FuzzerContext& context,
.calldata_hash = calldata_hash },
.calldata = calldata });
}

// Compute effective gas fees matching TS computeEffectiveGasFees
// This must be done after any mutation that could affect gas settings or global variables
tx_data.tx.effective_gas_fees =
compute_effective_gas_fees(tx_data.global_variables.gas_fees, tx_data.tx.gas_settings);

auto [mutated_serialized_fuzzer_data, mutated_serialized_fuzzer_data_size] = msgpack_encode_buffer(tx_data);
if (mutated_serialized_fuzzer_data_size > max_size) {
delete[] mutated_serialized_fuzzer_data;
Expand Down
139 changes: 33 additions & 106 deletions barretenberg/cpp/src/barretenberg/avm_fuzzer/mutations/tx_data.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#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/gas.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"
Expand Down Expand Up @@ -58,20 +59,6 @@ void mutate_teardown(std::optional<PublicCallRequestWithCalldata>& teardown_call

namespace bb::avm2::fuzzer {

// Gas bounds for mutation
constexpr uint32_t MIN_GAS = 1000;
constexpr uint32_t MAX_GAS = 10000000;

// Fee bounds for mutation
constexpr uint128_t MIN_FEE = 1;
constexpr uint128_t MAX_FEE = 1000;

constexpr uint32_t AVM_MAX_PROCESSABLE_DA_GAS = (MAX_NOTE_HASHES_PER_TX * AVM_EMITNOTEHASH_BASE_DA_GAS) +
(MAX_NULLIFIERS_PER_TX * AVM_EMITNULLIFIER_BASE_DA_GAS) +
(MAX_L2_TO_L1_MSGS_PER_TX * AVM_SENDL2TOL1MSG_BASE_DA_GAS) +
(MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX * AVM_SSTORE_DYN_DA_GAS) +
(PUBLIC_LOGS_LENGTH * AVM_EMITUNENCRYPTEDLOG_BASE_DA_GAS);

void mutate_tx(Tx& tx, std::vector<AztecAddress>& contract_addresses, std::mt19937_64& rng)
{
auto choice = TX_MUTATION_CONFIGURATION.select(rng);
Expand Down Expand Up @@ -102,98 +89,38 @@ void mutate_tx(Tx& tx, std::vector<AztecAddress>& contract_addresses, std::mt199
fuzz_info("Mutating revertible accumulated data");
mutate_revertible_accumulated_data(tx.revertible_accumulated_data, rng);
break;

// case 2:
// // Mutate gas_settings
// mutate_gas_settings(tx.gas_settings, rng);
// break;
// case 3:
// // Mutate effective_gas_fees
// mutate_gas_fees(tx.effective_gas_fees, rng);
// break;
// case 4:
// // Mutate Deployment data
// break;
// case 8:
// // Mutate gas_used_by_private
// break;
// case 9:
// // Mutate fee_payer
// break;
//}
}
}

void mutate_gas_settings(GasSettings& gas_settings, std::mt19937_64& rng)
{
auto choice = std::uniform_int_distribution<uint8_t>(0, 3)(rng);

switch (choice) {
case 0:
// Pick a Gas Limit between [0, AVM_MAX_PROCESSABLE_L2_GAS]
// fixme: probably should not mutate both l2_gas and da_gas to max in one go
gas_settings.gas_limits.l2_gas = std::uniform_int_distribution<uint32_t>(0, AVM_MAX_PROCESSABLE_L2_GAS)(rng);
gas_settings.gas_limits.da_gas = std::uniform_int_distribution<uint32_t>(0, AVM_MAX_PROCESSABLE_DA_GAS)(rng);
break;
case 1:
// Mutate teardown_gas_limits
gas_settings.teardown_gas_limits.l2_gas =
std::uniform_int_distribution<uint32_t>(0, AVM_MAX_PROCESSABLE_L2_GAS)(rng);
gas_settings.teardown_gas_limits.da_gas =
std::uniform_int_distribution<uint32_t>(0, AVM_MAX_PROCESSABLE_DA_GAS)(rng);
break;
case 2:
// Mutate max_fees_per_gas
// mutate_gas_fees(gas_settings.max_fees_per_gas, rng);
break;
case 3:
// Mutate max_priority_fees_per_gas
// mutate_gas_fees(gas_settings.max_priority_fees_per_gas, rng);
break;
}
}

void mutate_gas(Gas& gas, std::mt19937_64& rng)
{
auto choice = std::uniform_int_distribution<uint8_t>(0, 2)(rng);

switch (choice) {
case 0:
// Mutate l2_gas
gas.l2_gas = std::uniform_int_distribution<uint32_t>(MIN_GAS, MAX_GAS)(rng);
break;
case 1:
// Mutate da_gas
gas.da_gas = std::uniform_int_distribution<uint32_t>(MIN_GAS, MAX_GAS)(rng);
break;
case 2:
// Set both to same value
gas.l2_gas = gas.da_gas = std::uniform_int_distribution<uint32_t>(MIN_GAS, MAX_GAS)(rng);
break;
}
}

void mutate_gas_fees(GasFees& fees, std::mt19937_64& rng)
{
auto choice = std::uniform_int_distribution<uint8_t>(0, 3)(rng);

switch (choice) {
case 0:
// Mutate fee_per_da_gas
fees.fee_per_da_gas = std::uniform_int_distribution<uint64_t>(MIN_FEE, MAX_FEE)(rng);
break;
case 1:
// Mutate fee_per_l2_gas
fees.fee_per_l2_gas = std::uniform_int_distribution<uint64_t>(MIN_FEE, MAX_FEE)(rng);
break;
case 2:
// Set both to zero
fees.fee_per_da_gas = 0;
fees.fee_per_l2_gas = 0;
break;
case 3:
// Set both to same non-zero value
fees.fee_per_da_gas = fees.fee_per_l2_gas = std::uniform_int_distribution<uint64_t>(1, MAX_FEE)(rng);
case TxMutationOptions::GasSettings:
// Mutate gas_settings
fuzz_info("Mutating gas settings");
mutate_gas_settings(tx.gas_settings, rng);
// Ensure effective_gas_fees <= max_fees_per_gas after mutation
tx.effective_gas_fees.fee_per_da_gas =
std::min(tx.effective_gas_fees.fee_per_da_gas, tx.gas_settings.max_fees_per_gas.fee_per_da_gas);
tx.effective_gas_fees.fee_per_l2_gas =
std::min(tx.effective_gas_fees.fee_per_l2_gas, tx.gas_settings.max_fees_per_gas.fee_per_l2_gas);
break;
case TxMutationOptions::GasFees:
// Mutate effective_gas_fees
fuzz_info("Mutating effective gas fees");
mutate_gas_fees(tx.effective_gas_fees, rng);
// Ensure effective_gas_fees <= max_fees_per_gas after mutation
tx.effective_gas_fees.fee_per_da_gas =
std::min(tx.effective_gas_fees.fee_per_da_gas, tx.gas_settings.max_fees_per_gas.fee_per_da_gas);
tx.effective_gas_fees.fee_per_l2_gas =
std::min(tx.effective_gas_fees.fee_per_l2_gas, tx.gas_settings.max_fees_per_gas.fee_per_l2_gas);
break;
case TxMutationOptions::GasUsedByPrivate:
// Mutate gas_used_by_private
fuzz_info("Mutating gas used by private");
mutate_gas(tx.gas_used_by_private, rng);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do i need to check that this value is < gas_limits ? Or is it worthwhile trying out scenarios where this is not true?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As an improvement, we might want to generate taking into account the limit instead of generate + clamp, or we we'll overrepresent gas used by private == limit

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

or we could just generate it and then do modulo the limit

// Ensure gas_used_by_private <= gas_limits after mutation
tx.gas_used_by_private.l2_gas = std::min(tx.gas_used_by_private.l2_gas, tx.gas_settings.gas_limits.l2_gas);
tx.gas_used_by_private.da_gas = std::min(tx.gas_used_by_private.da_gas, tx.gas_settings.gas_limits.da_gas);
break;
case TxMutationOptions::FeePayer:
// Mutate fee_payer
fuzz_info("Mutating fee payer");
mutate_field(tx.fee_payer, rng, BASIC_FIELD_MUTATION_CONFIGURATION);
break;
}
}
Expand Down
19 changes: 9 additions & 10 deletions barretenberg/cpp/src/barretenberg/avm_fuzzer/mutations/tx_data.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,31 +15,30 @@ enum class TxMutationOptions {
TearDownEnqueuedCall,
NonRevertibleData,
RevertibleData,
GasSettings,
GasFees,
GasUsedByPrivate,
FeePayer
};

using TxMutationConfig = WeightedSelectionConfig<TxMutationOptions, 5>;
using TxMutationConfig = WeightedSelectionConfig<TxMutationOptions, 9>;

constexpr TxMutationConfig TX_MUTATION_CONFIGURATION = TxMutationConfig({
{ TxMutationOptions::SetupEnqueuedCalls, 30 },
{ TxMutationOptions::AppLogicEnqueuedCalls, 30 },
{ TxMutationOptions::TearDownEnqueuedCall, 10 },
{ TxMutationOptions::NonRevertibleData, 15 },
{ TxMutationOptions::RevertibleData, 15 },
{ TxMutationOptions::GasSettings, 5 },
{ TxMutationOptions::GasFees, 3 },
{ TxMutationOptions::GasUsedByPrivate, 1 },
{ TxMutationOptions::FeePayer, 1 },
});

namespace bb::avm2::fuzzer {

void mutate_tx(Tx& tx, std::vector<AztecAddress>& contract_addresses, std::mt19937_64& rng);

// GasSettings mutation
void mutate_gas_settings(GasSettings& gas_settings, std::mt19937_64& rng);

// Gas mutation
void mutate_gas(Gas& gas, std::mt19937_64& rng);

// GasFees mutation
void mutate_gas_fees(GasFees& fees, std::mt19937_64& rng);

void mutate_fuzzer_data_vec(const FuzzerContext& context,
std::vector<FuzzerData>& enqueued_calls,
std::mt19937_64& rng,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
#include "barretenberg/avm_fuzzer/mutations/tx_types/gas.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/common/serialize.hpp"
#include "barretenberg/numeric/uint256/uint256.hpp"
#include "barretenberg/vm2/common/avm_io.hpp"

using bb::avm2::AztecAddress;
using bb::avm2::FF;

namespace {

constexpr uint128_t MAX_U128 = ~static_cast<uint128_t>(0);

uint128_t generate_u128(std::mt19937_64& rng, uint128_t min = 0, uint128_t max = MAX_U128)
{
uint64_t high = std::uniform_int_distribution<uint64_t>()(rng);
uint64_t low = std::uniform_int_distribution<uint64_t>()(rng);
uint128_t value = (static_cast<uint128_t>(high) << 64) | static_cast<uint128_t>(low);
// Scale to desired range
return min + (value % (max - min + 1));
}

} // namespace

namespace bb::avm2::fuzzer {

Gas generate_gas(std::mt19937_64& rng)
{
uint32_t l2_gas = std::uniform_int_distribution<uint32_t>(MIN_GAS, AVM_MAX_PROCESSABLE_L2_GAS)(rng);
uint32_t da_gas = std::uniform_int_distribution<uint32_t>(MIN_GAS, AVM_MAX_PROCESSABLE_DA_GAS)(rng);

return Gas{ l2_gas, da_gas };
}

void mutate_gas(Gas& gas, std::mt19937_64& rng)
{
auto choice = std::uniform_int_distribution<uint8_t>(0, 1)(rng);

switch (choice) {
case 0:
// Mutate l2_gas
gas.l2_gas = std::uniform_int_distribution<uint32_t>(MIN_GAS, AVM_MAX_PROCESSABLE_L2_GAS)(rng);
break;
case 1:
// Mutate da_gas
gas.da_gas = std::uniform_int_distribution<uint32_t>(MIN_GAS, AVM_MAX_PROCESSABLE_DA_GAS)(rng);
break;
}
}

GasFees generate_gas_fees(std::mt19937_64& rng)
{
uint128_t fee_per_da_gas = generate_u128(rng, MIN_FEE, MAX_FEE);
uint128_t fee_per_l2_gas = generate_u128(rng, MIN_FEE, MAX_FEE);

return GasFees{
fee_per_da_gas,
fee_per_l2_gas,
};
}

void mutate_gas_fees(GasFees& fees, std::mt19937_64& rng)
{
auto choice = std::uniform_int_distribution<uint8_t>(0, 1)(rng);

switch (choice) {
case 0:
// Mutate fee_per_da_gas
fees.fee_per_da_gas = generate_u128(rng, MIN_FEE, MAX_FEE);
break;
case 1:
// Mutate fee_per_l2_gas
fees.fee_per_l2_gas = generate_u128(rng, MIN_FEE, MAX_FEE);
break;
}
}

GasSettings generate_gas_settings(std::mt19937_64& rng)
{
Gas gas_limits = generate_gas(rng);
Gas teardown_gas_limits = generate_gas(rng);
GasFees max_fees_per_gas = generate_gas_fees(rng);
GasFees max_priority_fees_per_gas = generate_gas_fees(rng);

return GasSettings{
gas_limits,
teardown_gas_limits,
max_fees_per_gas,
max_priority_fees_per_gas,
};
}

void mutate_gas_settings(GasSettings& gas_settings, std::mt19937_64& rng)
{
auto choice = GAS_SETTINGS_MUTATION_CONFIGURATION.select(rng);

switch (choice) {
case GasSettingsMutationOptions::GasLimits:
// Mutate gas_limits
mutate_gas(gas_settings.gas_limits, rng);
break;
case GasSettingsMutationOptions::TeardownGasLimits:
// Mutate teardown_gas_limits
mutate_gas(gas_settings.teardown_gas_limits, rng);
break;
case GasSettingsMutationOptions::MaxFeesPerGas:
// Mutate max_fees_per_gas
mutate_gas_fees(gas_settings.max_fees_per_gas, rng);
break;
case GasSettingsMutationOptions::MaxPriorityFeesPerGas:
// Mutate max_priority_fees_per_gas
mutate_gas_fees(gas_settings.max_priority_fees_per_gas, rng);
break;
}
}

GasFees compute_effective_gas_fees(const GasFees& gas_fees, const GasSettings& gas_settings)
{
// Match TS computeEffectiveGasFees from yarn-project/stdlib/src/fees/transaction_fee.ts
// priorityFees = min(maxPriorityFeesPerGas, maxFeesPerGas - gasFees)
// effectiveFees = gasFees + priorityFees
auto min_u128 = [](uint128_t a, uint128_t b) { return a < b ? a : b; };

uint128_t priority_da = min_u128(gas_settings.max_priority_fees_per_gas.fee_per_da_gas,
gas_settings.max_fees_per_gas.fee_per_da_gas - gas_fees.fee_per_da_gas);
uint128_t priority_l2 = min_u128(gas_settings.max_priority_fees_per_gas.fee_per_l2_gas,
gas_settings.max_fees_per_gas.fee_per_l2_gas - gas_fees.fee_per_l2_gas);

return GasFees{
.fee_per_da_gas = gas_fees.fee_per_da_gas + priority_da,
.fee_per_l2_gas = gas_fees.fee_per_l2_gas + priority_l2,
};
}

} // namespace bb::avm2::fuzzer
Loading