|
5 | 5 | #include "barretenberg/crypto/poseidon2/poseidon2.hpp" |
6 | 6 | #include "barretenberg/vm2/common/aztec_constants.hpp" |
7 | 7 | #include "barretenberg/vm2/common/aztec_types.hpp" |
| 8 | +#include "barretenberg/vm2/common/field.hpp" |
8 | 9 | #include "barretenberg/vm2/simulation/lib/contract_crypto.hpp" |
9 | 10 |
|
10 | 11 | extern "C" size_t LLVMFuzzerMutate(uint8_t* Data, size_t Size, size_t MaxSize); |
11 | 12 |
|
| 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 | + |
12 | 41 | namespace bb::avm2::fuzzer { |
13 | 42 |
|
14 | 43 | void mutate_bytecode(std::vector<ContractClassWithCommitment>& contract_classes, |
@@ -142,4 +171,63 @@ void mutate_contract_classes(std::vector<ContractClassWithCommitment>& contract_ |
142 | 171 | klass.id = new_class_id; |
143 | 172 | } |
144 | 173 |
|
| 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 | + |
145 | 233 | } // namespace bb::avm2::fuzzer |
0 commit comments