Skip to content

Commit 2b391cc

Browse files
committed
feat(avm): contract instance mutation
1 parent 3a173f8 commit 2b391cc

File tree

4 files changed

+98
-5
lines changed

4 files changed

+98
-5
lines changed

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -343,9 +343,9 @@ size_t mutate_tx_data(FuzzerContext& context,
343343
// So when we mutate contract classes, we also need to update the corresponding artifacts
344344

345345
break;
346-
// case TxDataMutationType::ContractInstanceMutation:
347-
// // Mutations here are likely to cause immediate failure
348-
// break;
346+
case FuzzerTxDataMutationType::ContractInstanceMutation:
347+
mutate_contract_instances(tx_data.contract_instances, tx_data.contract_addresses, rng);
348+
break;
349349
// case TxDataMutationType::GlobalVariablesMutation:
350350
// break;
351351
// case TxDataMutationType::ProtocolContractsMutation:

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

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,17 +62,18 @@ enum class FuzzerTxDataMutationType : uint8_t {
6262
TxMutation,
6363
BytecodeMutation,
6464
ContractClassMutation,
65-
// ContractInstanceMutation,
65+
ContractInstanceMutation,
6666
// GlobalVariablesMutation,
6767
// ProtocolContractsMutation
6868
};
6969

70-
using FuzzerTxDataMutationConfig = WeightedSelectionConfig<FuzzerTxDataMutationType, 3>;
70+
using FuzzerTxDataMutationConfig = WeightedSelectionConfig<FuzzerTxDataMutationType, 4>;
7171

7272
constexpr FuzzerTxDataMutationConfig FUZZER_TX_DATA_MUTATION_CONFIGURATION = FuzzerTxDataMutationConfig({
7373
{ FuzzerTxDataMutationType::TxMutation, 10 },
7474
{ FuzzerTxDataMutationType::BytecodeMutation, 1 },
7575
{ FuzzerTxDataMutationType::ContractClassMutation, 1 },
76+
{ FuzzerTxDataMutationType::ContractInstanceMutation, 1 },
7677
});
7778

7879
// Build bytecode and contract artifacts from fuzzer data

barretenberg/cpp/src/barretenberg/avm_fuzzer/mutations/bytecode.cpp

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,39 @@
55
#include "barretenberg/crypto/poseidon2/poseidon2.hpp"
66
#include "barretenberg/vm2/common/aztec_constants.hpp"
77
#include "barretenberg/vm2/common/aztec_types.hpp"
8+
#include "barretenberg/vm2/common/field.hpp"
89
#include "barretenberg/vm2/simulation/lib/contract_crypto.hpp"
910

1011
extern "C" size_t LLVMFuzzerMutate(uint8_t* Data, size_t Size, size_t MaxSize);
1112

13+
namespace {
14+
15+
avm2::Fq random_fq_scalar(std::mt19937_64& rng)
16+
{
17+
std::uniform_int_distribution<uint64_t> dist(0, std::numeric_limits<uint64_t>::max());
18+
19+
std::array<uint64_t, 4> limbs;
20+
for (size_t i = 0; i < 4; ++i) {
21+
limbs[i] = dist(rng);
22+
}
23+
24+
return avm2::Fq(limbs[0], limbs[1], limbs[2], limbs[3]);
25+
}
26+
27+
void mutate_point(AffinePoint& point, std::mt19937_64& rng)
28+
{
29+
// Generates a new valid on-curve point via scalar multiplication of the generator
30+
// We make some assumptions for this point mutation:
31+
// - The point is not at infinity
32+
// - The point is valid (on curve)
33+
34+
// Generate scalar
35+
Fq scalar = random_fq_scalar(rng);
36+
point = grumpkin::g1::affine_element::one() * scalar;
37+
}
38+
39+
} // namespace
40+
1241
namespace bb::avm2::fuzzer {
1342

1443
void mutate_bytecode(std::vector<ContractClassWithCommitment>& contract_classes,
@@ -142,4 +171,63 @@ void mutate_contract_classes(std::vector<ContractClassWithCommitment>& contract_
142171
klass.id = new_class_id;
143172
}
144173

174+
void mutate_contract_instances(std::vector<ContractInstance>& contract_instances,
175+
std::vector<AztecAddress>& contract_addresses,
176+
std::mt19937_64& rng)
177+
{
178+
// Skip if no contracts to mutate
179+
if (contract_instances.empty()) {
180+
return;
181+
}
182+
183+
// Select a random contract
184+
size_t idx = std::uniform_int_distribution<size_t>(0, contract_instances.size() - 1)(rng);
185+
186+
ContractInstance& instance = contract_instances[idx];
187+
auto original_address = simulation::compute_contract_address(instance);
188+
189+
// We don't mutate the class IDs here, only the other fields
190+
constexpr size_t num_mutable_fields = 7;
191+
auto choice = std::uniform_int_distribution<int>(0, num_mutable_fields - 1)(rng);
192+
switch (choice) {
193+
case 0:
194+
// Mutate salt
195+
mutate_field(instance.salt, rng, BASIC_FIELD_MUTATION_CONFIGURATION);
196+
break;
197+
case 1:
198+
// Mutate deployer
199+
mutate_field(instance.deployer, rng, BASIC_FIELD_MUTATION_CONFIGURATION);
200+
break;
201+
case 2:
202+
// Mutate initialization hash
203+
mutate_field(instance.initialization_hash, rng, BASIC_FIELD_MUTATION_CONFIGURATION);
204+
break;
205+
case 3:
206+
// Mutate nullifier key
207+
mutate_point(instance.public_keys.nullifier_key, rng);
208+
break;
209+
case 4:
210+
// Mutate incoming viewing key
211+
mutate_point(instance.public_keys.incoming_viewing_key, rng);
212+
break;
213+
case 5:
214+
// Mutate outgoing viewing key
215+
mutate_point(instance.public_keys.outgoing_viewing_key, rng);
216+
break;
217+
case 6:
218+
// Mutate tagging key
219+
mutate_point(instance.public_keys.tagging_key, rng);
220+
break;
221+
default:
222+
break;
223+
}
224+
225+
auto new_address = simulation::compute_contract_address(instance);
226+
227+
// This should always find a contract address, since we are mutating an existing instance
228+
auto contract_address =
229+
std::ranges::find_if(contract_addresses, [&](const AztecAddress& addr) { return addr == original_address; });
230+
*contract_address = new_address;
231+
}
232+
145233
} // namespace bb::avm2::fuzzer

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,4 +18,8 @@ void mutate_contract_classes(std::vector<ContractClassWithCommitment>& contract_
1818
std::vector<AztecAddress>& contract_addresses,
1919
std::mt19937_64& rng);
2020

21+
void mutate_contract_instances(std::vector<ContractInstance>& contract_instances,
22+
std::vector<AztecAddress>& contract_addresses,
23+
std::mt19937_64& rng);
24+
2125
} // namespace bb::avm2::fuzzer

0 commit comments

Comments
 (0)