Skip to content

Commit 1a1c595

Browse files
authored
feat(avm): fuzzer toradixbe (#19208)
To Radix BE for the fuzzer. Contains a method to generate the toradix "smartly" since there are many ways for it to fail early I folded the PR that was previously on top of this as it contained some fixes for toradixBE. That PR also had a bunch more stuff for L1L2MsgExists and MOV
1 parent aec59ed commit 1a1c595

File tree

5 files changed

+281
-2
lines changed

5 files changed

+281
-2
lines changed

barretenberg/cpp/src/barretenberg/avm_fuzzer/fuzz_lib/instruction.hpp

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -485,6 +485,15 @@ struct NULLIFIEREXISTS_Instruction {
485485
MSGPACK_FIELDS(nullifier_address, contract_address_address, result_address);
486486
};
487487

488+
/// @brief L1TOL2MSGEXISTS: Check if a L1 to L2 message exists
489+
/// M[result_address] = L1TOL2MSGEXISTS(M[msg_hash_address], M[leaf_index_address])
490+
struct L1TOL2MSGEXISTS_Instruction {
491+
ParamRef msg_hash_address; // FF: the message hash
492+
ParamRef leaf_index_address; // U64: leaf index in the message tree
493+
AddressRef result_address; // result (U1)
494+
MSGPACK_FIELDS(msg_hash_address, leaf_index_address, result_address);
495+
};
496+
488497
/// @brief EMITNOTEHASH: M[note_hash_offset] = note_hash; emit note hash to the note hash tree
489498
struct EMITNOTEHASH_Instruction {
490499
AddressRef note_hash_address; // absolute address where the note hash will be stored
@@ -624,6 +633,18 @@ struct SHA256COMPRESSION_Instruction {
624633
MSGPACK_FIELDS(state_address, input_address, dst_address);
625634
};
626635

636+
/// @brief TORADIXBE: Convert a field element to a vector of limbs in big-endian radix representation
637+
/// M[dst_address:dst_address+num_limbs] = to_radix_be(M[value_address], radix, num_limbs)
638+
struct TORADIXBE_Instruction {
639+
ParamRef value_address; // FF: value to convert
640+
ParamRef radix_address; // U32: the radix/base
641+
ParamRef num_limbs_address; // U32: number of output limbs
642+
ParamRef output_bits_address; // U1: whether output is bits
643+
AddressRef dst_address; // destination for limbs
644+
bool is_output_bits; // known at generation time for memory tracking (U1 if true, U8 if false)
645+
MSGPACK_FIELDS(value_address, radix_address, num_limbs_address, output_bits_address, dst_address, is_output_bits);
646+
};
647+
627648
using FuzzInstruction = std::variant<ADD_8_Instruction,
628649
FDIV_8_Instruction,
629650
SET_8_Instruction,
@@ -667,6 +688,7 @@ using FuzzInstruction = std::variant<ADD_8_Instruction,
667688
GETENVVAR_Instruction,
668689
EMITNULLIFIER_Instruction,
669690
NULLIFIEREXISTS_Instruction,
691+
L1TOL2MSGEXISTS_Instruction,
670692
EMITNOTEHASH_Instruction,
671693
NOTEHASHEXISTS_Instruction,
672694
CALLDATACOPY_Instruction,
@@ -679,7 +701,8 @@ using FuzzInstruction = std::variant<ADD_8_Instruction,
679701
ECADD_Instruction,
680702
POSEIDON2PERM_Instruction,
681703
KECCAKF1600_Instruction,
682-
SHA256COMPRESSION_Instruction>;
704+
SHA256COMPRESSION_Instruction,
705+
TORADIXBE_Instruction>;
683706

684707
template <class... Ts> struct overloaded : Ts... {
685708
using Ts::operator()...;
@@ -841,6 +864,10 @@ inline std::ostream& operator<<(std::ostream& os, const FuzzInstruction& instruc
841864
os << "NULLIFIEREXISTS_Instruction " << arg.nullifier_address << " " << arg.contract_address_address
842865
<< " " << arg.result_address;
843866
},
867+
[&](L1TOL2MSGEXISTS_Instruction arg) {
868+
os << "L1TOL2MSGEXISTS_Instruction " << arg.msg_hash_address << " " << arg.leaf_index_address << " "
869+
<< arg.result_address;
870+
},
844871
[&](EMITNOTEHASH_Instruction arg) {
845872
os << "EMITNOTEHASH_Instruction " << arg.note_hash_address << " " << arg.note_hash;
846873
},
@@ -886,6 +913,11 @@ inline std::ostream& operator<<(std::ostream& os, const FuzzInstruction& instruc
886913
os << "SHA256COMPRESSION_Instruction " << arg.state_address << " " << arg.input_address << " "
887914
<< arg.dst_address;
888915
},
916+
[&](TORADIXBE_Instruction arg) {
917+
os << "TORADIXBE_Instruction " << arg.value_address << " " << arg.radix_address << " "
918+
<< arg.num_limbs_address << " " << arg.output_bits_address << " " << arg.dst_address << " "
919+
<< arg.is_output_bits;
920+
},
889921
[&](auto) { os << "Unknown instruction"; },
890922
},
891923
instruction);

barretenberg/cpp/src/barretenberg/avm_fuzzer/fuzz_lib/program_block.cpp

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1494,6 +1494,62 @@ void ProgramBlock::process_sha256compression_instruction(SHA256COMPRESSION_Instr
14941494
}
14951495
}
14961496

1497+
void ProgramBlock::process_l1tol2msgexists_instruction(L1TOL2MSGEXISTS_Instruction instruction)
1498+
{
1499+
auto msg_hash_operand = memory_manager.get_resolved_address_and_operand_16(instruction.msg_hash_address);
1500+
auto leaf_index_operand = memory_manager.get_resolved_address_and_operand_16(instruction.leaf_index_address);
1501+
auto result_operand = memory_manager.get_resolved_address_and_operand_16(instruction.result_address);
1502+
1503+
if (!msg_hash_operand.has_value() || !leaf_index_operand.has_value() || !result_operand.has_value()) {
1504+
return;
1505+
}
1506+
1507+
preprocess_memory_addresses(msg_hash_operand.value().first);
1508+
preprocess_memory_addresses(leaf_index_operand.value().first);
1509+
preprocess_memory_addresses(result_operand.value().first);
1510+
1511+
auto l1tol2msgexists_instruction = bb::avm2::testing::InstructionBuilder(bb::avm2::WireOpCode::L1TOL2MSGEXISTS)
1512+
.operand(msg_hash_operand.value().second)
1513+
.operand(leaf_index_operand.value().second)
1514+
.operand(result_operand.value().second)
1515+
.build();
1516+
instructions.push_back(l1tol2msgexists_instruction);
1517+
memory_manager.set_memory_address(bb::avm2::MemoryTag::U1, result_operand.value().first.absolute_address);
1518+
}
1519+
1520+
void ProgramBlock::process_toradixbe_instruction(TORADIXBE_Instruction instruction)
1521+
{
1522+
auto value_operand = memory_manager.get_resolved_address_and_operand_16(instruction.value_address);
1523+
auto radix_operand = memory_manager.get_resolved_address_and_operand_16(instruction.radix_address);
1524+
auto num_limbs_operand = memory_manager.get_resolved_address_and_operand_16(instruction.num_limbs_address);
1525+
auto output_bits_operand = memory_manager.get_resolved_address_and_operand_16(instruction.output_bits_address);
1526+
auto dst_operand = memory_manager.get_resolved_address_and_operand_16(instruction.dst_address);
1527+
1528+
if (!value_operand.has_value() || !radix_operand.has_value() || !num_limbs_operand.has_value() ||
1529+
!output_bits_operand.has_value() || !dst_operand.has_value()) {
1530+
return;
1531+
}
1532+
1533+
preprocess_memory_addresses(value_operand.value().first);
1534+
preprocess_memory_addresses(radix_operand.value().first);
1535+
preprocess_memory_addresses(num_limbs_operand.value().first);
1536+
preprocess_memory_addresses(output_bits_operand.value().first);
1537+
preprocess_memory_addresses(dst_operand.value().first);
1538+
1539+
auto toradixbe_instruction = bb::avm2::testing::InstructionBuilder(bb::avm2::WireOpCode::TORADIXBE)
1540+
.operand(dst_operand.value().second)
1541+
.operand(value_operand.value().second)
1542+
.operand(radix_operand.value().second)
1543+
.operand(num_limbs_operand.value().second)
1544+
.operand(output_bits_operand.value().second)
1545+
.build();
1546+
instructions.push_back(toradixbe_instruction);
1547+
1548+
// Use is_output_bits to determine the output memory tag
1549+
auto output_tag = instruction.is_output_bits ? bb::avm2::MemoryTag::U1 : bb::avm2::MemoryTag::U8;
1550+
memory_manager.set_memory_address(output_tag, dst_operand.value().first.absolute_address);
1551+
}
1552+
14971553
void ProgramBlock::finalize_with_return(uint8_t return_size,
14981554
MemoryTagWrapper return_value_tag,
14991555
uint16_t return_value_offset_index)
@@ -1682,6 +1738,10 @@ void ProgramBlock::process_instruction(FuzzInstruction instruction)
16821738
[this](SHA256COMPRESSION_Instruction instruction) {
16831739
return this->process_sha256compression_instruction(instruction);
16841740
},
1741+
[this](L1TOL2MSGEXISTS_Instruction instruction) {
1742+
return this->process_l1tol2msgexists_instruction(instruction);
1743+
},
1744+
[this](TORADIXBE_Instruction instruction) { return this->process_toradixbe_instruction(instruction); },
16851745
[](auto) { throw std::runtime_error("Unknown instruction"); },
16861746
},
16871747
instruction);

barretenberg/cpp/src/barretenberg/avm_fuzzer/fuzz_lib/program_block.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,8 @@ class ProgramBlock {
110110
void process_poseidon2perm_instruction(POSEIDON2PERM_Instruction instruction);
111111
void process_keccakf1600_instruction(KECCAKF1600_Instruction instruction);
112112
void process_sha256compression_instruction(SHA256COMPRESSION_Instruction instruction);
113+
void process_l1tol2msgexists_instruction(L1TOL2MSGEXISTS_Instruction instruction);
114+
void process_toradixbe_instruction(TORADIXBE_Instruction instruction);
113115

114116
public:
115117
std::vector<ProgramBlock*> successors;

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

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,8 @@ enum class InstructionGenerationOptions {
237237
SET_64,
238238
SET_128,
239239
SET_FF,
240+
MOV_8,
241+
MOV_16,
240242
ADD_16,
241243
SUB_16,
242244
MUL_16,
@@ -258,6 +260,7 @@ enum class InstructionGenerationOptions {
258260
GETENVVAR,
259261
EMITNULLIFIER,
260262
NULLIFIEREXISTS,
263+
L1TOL2MSGEXISTS,
261264
EMITNOTEHASH,
262265
NOTEHASHEXISTS,
263266
CALLDATACOPY,
@@ -271,9 +274,10 @@ enum class InstructionGenerationOptions {
271274
POSEIDON2PERM,
272275
KECCAKF1600,
273276
SHA256COMPRESSION,
277+
TORADIXBE,
274278
};
275279

276-
using InstructionGenerationConfig = WeightedSelectionConfig<InstructionGenerationOptions, 54>;
280+
using InstructionGenerationConfig = WeightedSelectionConfig<InstructionGenerationOptions, 58>;
277281

278282
constexpr InstructionGenerationConfig BASIC_INSTRUCTION_GENERATION_CONFIGURATION = InstructionGenerationConfig({
279283
{ InstructionGenerationOptions::ADD_8, 1 },
@@ -296,6 +300,8 @@ constexpr InstructionGenerationConfig BASIC_INSTRUCTION_GENERATION_CONFIGURATION
296300
{ InstructionGenerationOptions::SET_64, 1 },
297301
{ InstructionGenerationOptions::SET_128, 1 },
298302
{ InstructionGenerationOptions::SET_FF, 1 },
303+
{ InstructionGenerationOptions::MOV_8, 1 },
304+
{ InstructionGenerationOptions::MOV_16, 1 },
299305
{ InstructionGenerationOptions::ADD_16, 1 },
300306
{ InstructionGenerationOptions::SUB_16, 1 },
301307
{ InstructionGenerationOptions::MUL_16, 1 },
@@ -317,6 +323,7 @@ constexpr InstructionGenerationConfig BASIC_INSTRUCTION_GENERATION_CONFIGURATION
317323
{ InstructionGenerationOptions::GETENVVAR, 1 },
318324
{ InstructionGenerationOptions::EMITNULLIFIER, 1 },
319325
{ InstructionGenerationOptions::NULLIFIEREXISTS, 1 },
326+
{ InstructionGenerationOptions::L1TOL2MSGEXISTS, 1 },
320327
{ InstructionGenerationOptions::EMITNOTEHASH, 1 },
321328
{ InstructionGenerationOptions::NOTEHASHEXISTS, 1 },
322329
{ InstructionGenerationOptions::CALLDATACOPY, 1 },
@@ -330,6 +337,7 @@ constexpr InstructionGenerationConfig BASIC_INSTRUCTION_GENERATION_CONFIGURATION
330337
{ InstructionGenerationOptions::POSEIDON2PERM, 1 },
331338
{ InstructionGenerationOptions::KECCAKF1600, 1 },
332339
{ InstructionGenerationOptions::SHA256COMPRESSION, 1 },
340+
{ InstructionGenerationOptions::TORADIXBE, 1 },
333341
});
334342

335343
enum class SStoreMutationOptions { src_address, result_address, slot };
@@ -367,6 +375,15 @@ constexpr NullifierExistsMutationConfig BASIC_NULLIFIER_EXISTS_MUTATION_CONFIGUR
367375
{ NullifierExistsMutationOptions::result_address, 1 },
368376
});
369377

378+
enum class L1ToL2MsgExistsMutationOptions { msg_hash_address, leaf_index_address, result_address };
379+
using L1ToL2MsgExistsMutationConfig = WeightedSelectionConfig<L1ToL2MsgExistsMutationOptions, 3>;
380+
381+
constexpr L1ToL2MsgExistsMutationConfig BASIC_L1TOL2MSGEXISTS_MUTATION_CONFIGURATION = L1ToL2MsgExistsMutationConfig({
382+
{ L1ToL2MsgExistsMutationOptions::msg_hash_address, 1 },
383+
{ L1ToL2MsgExistsMutationOptions::leaf_index_address, 1 },
384+
{ L1ToL2MsgExistsMutationOptions::result_address, 1 },
385+
});
386+
370387
enum class EmitNoteHashMutationOptions { note_hash_address, note_hash };
371388
using EmitNoteHashMutationConfig = WeightedSelectionConfig<EmitNoteHashMutationOptions, 2>;
372389

@@ -473,6 +490,25 @@ constexpr SuccessCopyMutationConfig BASIC_SUCCESSCOPY_MUTATION_CONFIGURATION = S
473490
{ SuccessCopyMutationOptions::dst_address, 1 },
474491
});
475492

493+
enum class ToRadixBEMutationOptions {
494+
value_address,
495+
radix_address,
496+
num_limbs_address,
497+
output_bits_address,
498+
dst_address,
499+
is_output_bits
500+
};
501+
using ToRadixBEMutationConfig = WeightedSelectionConfig<ToRadixBEMutationOptions, 6>;
502+
503+
constexpr ToRadixBEMutationConfig BASIC_TORADIXBE_MUTATION_CONFIGURATION = ToRadixBEMutationConfig({
504+
{ ToRadixBEMutationOptions::value_address, 1 },
505+
{ ToRadixBEMutationOptions::radix_address, 1 },
506+
{ ToRadixBEMutationOptions::num_limbs_address, 1 },
507+
{ ToRadixBEMutationOptions::output_bits_address, 1 },
508+
{ ToRadixBEMutationOptions::dst_address, 1 },
509+
{ ToRadixBEMutationOptions::is_output_bits, 1 },
510+
});
511+
476512
enum class ReturnOptionsMutationOptions { return_size, return_value_tag, return_value_offset_index };
477513

478514
using ReturnOptionsMutationConfig = WeightedSelectionConfig<ReturnOptionsMutationOptions, 3>;

0 commit comments

Comments
 (0)