Skip to content

Commit 193d8a7

Browse files
committed
feat(avm): gas mutations
1 parent 2308b5b commit 193d8a7

File tree

5 files changed

+239
-116
lines changed

5 files changed

+239
-116
lines changed

barretenberg/cpp/src/barretenberg/avm_fuzzer/fuzzer_lib.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include "barretenberg/avm_fuzzer/fuzzer_comparison_helper.hpp"
1414
#include "barretenberg/avm_fuzzer/mutations/fuzzer_data.hpp"
1515
#include "barretenberg/avm_fuzzer/mutations/tx_data.hpp"
16+
#include "barretenberg/avm_fuzzer/mutations/tx_types/gas.hpp"
1617
#include "barretenberg/common/log.hpp"
1718
#include "barretenberg/vm2/avm_api.hpp"
1819
#include "barretenberg/vm2/common/avm_io.hpp"
@@ -333,6 +334,12 @@ size_t mutate_tx_data(FuzzerContext& context,
333334
.calldata_hash = calldata_hash },
334335
.calldata = calldata });
335336
}
337+
338+
// Compute effective gas fees matching TS computeEffectiveGasFees
339+
// This must be done after any mutation that could affect gas settings or global variables
340+
tx_data.tx.effective_gas_fees =
341+
compute_effective_gas_fees(tx_data.global_variables.gas_fees, tx_data.tx.gas_settings);
342+
336343
auto [mutated_serialized_fuzzer_data, mutated_serialized_fuzzer_data_size] = msgpack_encode_buffer(tx_data);
337344
if (mutated_serialized_fuzzer_data_size > max_size) {
338345
delete[] mutated_serialized_fuzzer_data;

barretenberg/cpp/src/barretenberg/avm_fuzzer/mutations/tx_data.cpp

Lines changed: 30 additions & 106 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include "barretenberg/avm_fuzzer/mutations/fuzzer_data.hpp"
77
#include "barretenberg/avm_fuzzer/mutations/instructions/instruction_block.hpp"
88
#include "barretenberg/avm_fuzzer/mutations/tx_types/accumulated_data.hpp"
9+
#include "barretenberg/avm_fuzzer/mutations/tx_types/gas.hpp"
910
#include "barretenberg/avm_fuzzer/mutations/tx_types/public_call_request.hpp"
1011
#include "barretenberg/vm2/common/avm_io.hpp"
1112
#include "barretenberg/vm2/common/aztec_constants.hpp"
@@ -58,20 +59,6 @@ void mutate_teardown(std::optional<PublicCallRequestWithCalldata>& teardown_call
5859

5960
namespace bb::avm2::fuzzer {
6061

61-
// Gas bounds for mutation
62-
constexpr uint32_t MIN_GAS = 1000;
63-
constexpr uint32_t MAX_GAS = 10000000;
64-
65-
// Fee bounds for mutation
66-
constexpr uint128_t MIN_FEE = 1;
67-
constexpr uint128_t MAX_FEE = 1000;
68-
69-
constexpr uint32_t AVM_MAX_PROCESSABLE_DA_GAS = (MAX_NOTE_HASHES_PER_TX * AVM_EMITNOTEHASH_BASE_DA_GAS) +
70-
(MAX_NULLIFIERS_PER_TX * AVM_EMITNULLIFIER_BASE_DA_GAS) +
71-
(MAX_L2_TO_L1_MSGS_PER_TX * AVM_SENDL2TOL1MSG_BASE_DA_GAS) +
72-
(MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX * AVM_SSTORE_DYN_DA_GAS) +
73-
(PUBLIC_LOGS_LENGTH * AVM_EMITUNENCRYPTEDLOG_BASE_DA_GAS);
74-
7562
void mutate_tx(Tx& tx, std::vector<AztecAddress>& contract_addresses, std::mt19937_64& rng)
7663
{
7764
auto choice = TX_MUTATION_CONFIGURATION.select(rng);
@@ -102,98 +89,35 @@ void mutate_tx(Tx& tx, std::vector<AztecAddress>& contract_addresses, std::mt199
10289
fuzz_info("Mutating revertible accumulated data");
10390
mutate_revertible_accumulated_data(tx.revertible_accumulated_data, rng);
10491
break;
105-
106-
// case 2:
107-
// // Mutate gas_settings
108-
// mutate_gas_settings(tx.gas_settings, rng);
109-
// break;
110-
// case 3:
111-
// // Mutate effective_gas_fees
112-
// mutate_gas_fees(tx.effective_gas_fees, rng);
113-
// break;
114-
// case 4:
115-
// // Mutate Deployment data
116-
// break;
117-
// case 8:
118-
// // Mutate gas_used_by_private
119-
// break;
120-
// case 9:
121-
// // Mutate fee_payer
122-
// break;
123-
//}
124-
}
125-
}
126-
127-
void mutate_gas_settings(GasSettings& gas_settings, std::mt19937_64& rng)
128-
{
129-
auto choice = std::uniform_int_distribution<uint8_t>(0, 3)(rng);
130-
131-
switch (choice) {
132-
case 0:
133-
// Pick a Gas Limit between [0, AVM_MAX_PROCESSABLE_L2_GAS]
134-
// fixme: probably should not mutate both l2_gas and da_gas to max in one go
135-
gas_settings.gas_limits.l2_gas = std::uniform_int_distribution<uint32_t>(0, AVM_MAX_PROCESSABLE_L2_GAS)(rng);
136-
gas_settings.gas_limits.da_gas = std::uniform_int_distribution<uint32_t>(0, AVM_MAX_PROCESSABLE_DA_GAS)(rng);
137-
break;
138-
case 1:
139-
// Mutate teardown_gas_limits
140-
gas_settings.teardown_gas_limits.l2_gas =
141-
std::uniform_int_distribution<uint32_t>(0, AVM_MAX_PROCESSABLE_L2_GAS)(rng);
142-
gas_settings.teardown_gas_limits.da_gas =
143-
std::uniform_int_distribution<uint32_t>(0, AVM_MAX_PROCESSABLE_DA_GAS)(rng);
144-
break;
145-
case 2:
146-
// Mutate max_fees_per_gas
147-
// mutate_gas_fees(gas_settings.max_fees_per_gas, rng);
148-
break;
149-
case 3:
150-
// Mutate max_priority_fees_per_gas
151-
// mutate_gas_fees(gas_settings.max_priority_fees_per_gas, rng);
152-
break;
153-
}
154-
}
155-
156-
void mutate_gas(Gas& gas, std::mt19937_64& rng)
157-
{
158-
auto choice = std::uniform_int_distribution<uint8_t>(0, 2)(rng);
159-
160-
switch (choice) {
161-
case 0:
162-
// Mutate l2_gas
163-
gas.l2_gas = std::uniform_int_distribution<uint32_t>(MIN_GAS, MAX_GAS)(rng);
164-
break;
165-
case 1:
166-
// Mutate da_gas
167-
gas.da_gas = std::uniform_int_distribution<uint32_t>(MIN_GAS, MAX_GAS)(rng);
168-
break;
169-
case 2:
170-
// Set both to same value
171-
gas.l2_gas = gas.da_gas = std::uniform_int_distribution<uint32_t>(MIN_GAS, MAX_GAS)(rng);
172-
break;
173-
}
174-
}
175-
176-
void mutate_gas_fees(GasFees& fees, std::mt19937_64& rng)
177-
{
178-
auto choice = std::uniform_int_distribution<uint8_t>(0, 3)(rng);
179-
180-
switch (choice) {
181-
case 0:
182-
// Mutate fee_per_da_gas
183-
fees.fee_per_da_gas = std::uniform_int_distribution<uint64_t>(MIN_FEE, MAX_FEE)(rng);
184-
break;
185-
case 1:
186-
// Mutate fee_per_l2_gas
187-
fees.fee_per_l2_gas = std::uniform_int_distribution<uint64_t>(MIN_FEE, MAX_FEE)(rng);
188-
break;
189-
case 2:
190-
// Set both to zero
191-
fees.fee_per_da_gas = 0;
192-
fees.fee_per_l2_gas = 0;
193-
break;
194-
case 3:
195-
// Set both to same non-zero value
196-
fees.fee_per_da_gas = fees.fee_per_l2_gas = std::uniform_int_distribution<uint64_t>(1, MAX_FEE)(rng);
92+
case TxMutationOptions::GasSettings:
93+
// Mutate gas_settings
94+
fuzz_info("Mutating gas settings");
95+
mutate_gas_settings(tx.gas_settings, rng);
96+
// Ensure effective_gas_fees <= max_fees_per_gas after mutation
97+
tx.effective_gas_fees.fee_per_da_gas =
98+
std::min(tx.effective_gas_fees.fee_per_da_gas, tx.gas_settings.max_fees_per_gas.fee_per_da_gas);
99+
tx.effective_gas_fees.fee_per_l2_gas =
100+
std::min(tx.effective_gas_fees.fee_per_l2_gas, tx.gas_settings.max_fees_per_gas.fee_per_l2_gas);
101+
break;
102+
case TxMutationOptions::GasFees:
103+
// Mutate effective_gas_fees
104+
fuzz_info("Mutating effective gas fees");
105+
mutate_gas_fees(tx.effective_gas_fees, rng);
106+
// Ensure effective_gas_fees <= max_fees_per_gas after mutation
107+
tx.effective_gas_fees.fee_per_da_gas =
108+
std::min(tx.effective_gas_fees.fee_per_da_gas, tx.gas_settings.max_fees_per_gas.fee_per_da_gas);
109+
tx.effective_gas_fees.fee_per_l2_gas =
110+
std::min(tx.effective_gas_fees.fee_per_l2_gas, tx.gas_settings.max_fees_per_gas.fee_per_l2_gas);
111+
break;
112+
case TxMutationOptions::GasUsedByPrivate:
113+
// Mutate gas_used_by_private
114+
fuzz_info("Mutating gas used by private");
115+
mutate_gas(tx.gas_used_by_private, rng);
116+
break;
117+
case TxMutationOptions::FeePayer:
118+
// Mutate fee_payer
119+
fuzz_info("Mutating fee payer");
120+
mutate_field(tx.fee_payer, rng, BASIC_FIELD_MUTATION_CONFIGURATION);
197121
break;
198122
}
199123
}

barretenberg/cpp/src/barretenberg/avm_fuzzer/mutations/tx_data.hpp

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -15,31 +15,30 @@ enum class TxMutationOptions {
1515
TearDownEnqueuedCall,
1616
NonRevertibleData,
1717
RevertibleData,
18+
GasSettings,
19+
GasFees,
20+
GasUsedByPrivate,
21+
FeePayer
1822
};
1923

20-
using TxMutationConfig = WeightedSelectionConfig<TxMutationOptions, 5>;
24+
using TxMutationConfig = WeightedSelectionConfig<TxMutationOptions, 9>;
2125

2226
constexpr TxMutationConfig TX_MUTATION_CONFIGURATION = TxMutationConfig({
2327
{ TxMutationOptions::SetupEnqueuedCalls, 30 },
2428
{ TxMutationOptions::AppLogicEnqueuedCalls, 30 },
2529
{ TxMutationOptions::TearDownEnqueuedCall, 10 },
2630
{ TxMutationOptions::NonRevertibleData, 15 },
2731
{ TxMutationOptions::RevertibleData, 15 },
32+
{ TxMutationOptions::GasSettings, 5 },
33+
{ TxMutationOptions::GasFees, 3 },
34+
{ TxMutationOptions::GasUsedByPrivate, 1 },
35+
{ TxMutationOptions::FeePayer, 1 },
2836
});
2937

3038
namespace bb::avm2::fuzzer {
3139

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

34-
// GasSettings mutation
35-
void mutate_gas_settings(GasSettings& gas_settings, std::mt19937_64& rng);
36-
37-
// Gas mutation
38-
void mutate_gas(Gas& gas, std::mt19937_64& rng);
39-
40-
// GasFees mutation
41-
void mutate_gas_fees(GasFees& fees, std::mt19937_64& rng);
42-
4342
void mutate_fuzzer_data_vec(const FuzzerContext& context,
4443
std::vector<FuzzerData>& enqueued_calls,
4544
std::mt19937_64& rng,
Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
#include "barretenberg/avm_fuzzer/mutations/tx_types/gas.hpp"
2+
3+
#include "barretenberg/avm_fuzzer/fuzz_lib/constants.hpp"
4+
#include "barretenberg/avm_fuzzer/mutations/basic_types/field.hpp"
5+
#include "barretenberg/avm_fuzzer/mutations/basic_types/vector.hpp"
6+
#include "barretenberg/avm_fuzzer/mutations/configuration.hpp"
7+
#include "barretenberg/common/serialize.hpp"
8+
#include "barretenberg/numeric/uint256/uint256.hpp"
9+
#include "barretenberg/vm2/common/avm_io.hpp"
10+
11+
using bb::avm2::AztecAddress;
12+
using bb::avm2::FF;
13+
14+
namespace {
15+
16+
constexpr uint128_t MAX_U128 = ~static_cast<uint128_t>(0);
17+
18+
uint128_t generate_u128(std::mt19937_64& rng, uint128_t min = 0, uint128_t max = MAX_U128)
19+
{
20+
uint64_t high = std::uniform_int_distribution<uint64_t>()(rng);
21+
uint64_t low = std::uniform_int_distribution<uint64_t>()(rng);
22+
uint128_t value = (static_cast<uint128_t>(high) << 64) | static_cast<uint128_t>(low);
23+
// Scale to desired range
24+
return min + (value % (max - min + 1));
25+
}
26+
27+
} // namespace
28+
29+
namespace bb::avm2::fuzzer {
30+
31+
Gas generate_gas(std::mt19937_64& rng)
32+
{
33+
uint32_t l2_gas = std::uniform_int_distribution<uint32_t>(MIN_GAS, AVM_MAX_PROCESSABLE_L2_GAS)(rng);
34+
uint32_t da_gas = std::uniform_int_distribution<uint32_t>(MIN_GAS, AVM_MAX_PROCESSABLE_DA_GAS)(rng);
35+
36+
return Gas{ l2_gas, da_gas };
37+
}
38+
39+
void mutate_gas(Gas& gas, std::mt19937_64& rng)
40+
{
41+
auto choice = std::uniform_int_distribution<uint8_t>(0, 1)(rng);
42+
43+
switch (choice) {
44+
case 0:
45+
// Mutate l2_gas
46+
gas.l2_gas = std::uniform_int_distribution<uint32_t>(MIN_GAS, AVM_MAX_PROCESSABLE_L2_GAS)(rng);
47+
break;
48+
case 1:
49+
// Mutate da_gas
50+
gas.da_gas = std::uniform_int_distribution<uint32_t>(MIN_GAS, AVM_MAX_PROCESSABLE_DA_GAS)(rng);
51+
break;
52+
}
53+
}
54+
55+
GasFees generate_gas_fees(std::mt19937_64& rng)
56+
{
57+
uint128_t fee_per_da_gas = generate_u128(rng, MIN_FEE, MAX_FEE);
58+
uint128_t fee_per_l2_gas = generate_u128(rng, MIN_FEE, MAX_FEE);
59+
60+
return GasFees{
61+
fee_per_da_gas,
62+
fee_per_l2_gas,
63+
};
64+
}
65+
66+
void mutate_gas_fees(GasFees& fees, std::mt19937_64& rng)
67+
{
68+
auto choice = std::uniform_int_distribution<uint8_t>(0, 1)(rng);
69+
70+
switch (choice) {
71+
case 0:
72+
// Mutate fee_per_da_gas
73+
fees.fee_per_da_gas = generate_u128(rng, MIN_FEE, MAX_FEE);
74+
break;
75+
case 1:
76+
// Mutate fee_per_l2_gas
77+
fees.fee_per_l2_gas = generate_u128(rng, MIN_FEE, MAX_FEE);
78+
break;
79+
}
80+
}
81+
82+
GasSettings generate_gas_settings(std::mt19937_64& rng)
83+
{
84+
Gas gas_limits = generate_gas(rng);
85+
Gas teardown_gas_limits = generate_gas(rng);
86+
GasFees max_fees_per_gas = generate_gas_fees(rng);
87+
GasFees max_priority_fees_per_gas = generate_gas_fees(rng);
88+
89+
return GasSettings{
90+
gas_limits,
91+
teardown_gas_limits,
92+
max_fees_per_gas,
93+
max_priority_fees_per_gas,
94+
};
95+
}
96+
97+
void mutate_gas_settings(GasSettings& gas_settings, std::mt19937_64& rng)
98+
{
99+
auto choice = GAS_SETTINGS_MUTATION_CONFIGURATION.select(rng);
100+
101+
switch (choice) {
102+
case GasSettingsMutationOptions::GasLimits:
103+
// Mutate gas_limits
104+
mutate_gas(gas_settings.gas_limits, rng);
105+
break;
106+
case GasSettingsMutationOptions::TeardownGasLimits:
107+
// Mutate teardown_gas_limits
108+
mutate_gas(gas_settings.teardown_gas_limits, rng);
109+
break;
110+
case GasSettingsMutationOptions::MaxFeesPerGas:
111+
// Mutate max_fees_per_gas
112+
mutate_gas_fees(gas_settings.max_fees_per_gas, rng);
113+
break;
114+
case GasSettingsMutationOptions::MaxPriorityFeesPerGas:
115+
// Mutate max_priority_fees_per_gas
116+
mutate_gas_fees(gas_settings.max_priority_fees_per_gas, rng);
117+
break;
118+
}
119+
}
120+
121+
GasFees compute_effective_gas_fees(const GasFees& gas_fees, const GasSettings& gas_settings)
122+
{
123+
// Match TS computeEffectiveGasFees from yarn-project/stdlib/src/fees/transaction_fee.ts
124+
// priorityFees = min(maxPriorityFeesPerGas, maxFeesPerGas - gasFees)
125+
// effectiveFees = gasFees + priorityFees
126+
auto min_u128 = [](uint128_t a, uint128_t b) { return a < b ? a : b; };
127+
128+
uint128_t priority_da = min_u128(gas_settings.max_priority_fees_per_gas.fee_per_da_gas,
129+
gas_settings.max_fees_per_gas.fee_per_da_gas - gas_fees.fee_per_da_gas);
130+
uint128_t priority_l2 = min_u128(gas_settings.max_priority_fees_per_gas.fee_per_l2_gas,
131+
gas_settings.max_fees_per_gas.fee_per_l2_gas - gas_fees.fee_per_l2_gas);
132+
133+
return GasFees{
134+
.fee_per_da_gas = gas_fees.fee_per_da_gas + priority_da,
135+
.fee_per_l2_gas = gas_fees.fee_per_l2_gas + priority_l2,
136+
};
137+
}
138+
139+
} // namespace bb::avm2::fuzzer

0 commit comments

Comments
 (0)