@@ -51,7 +51,8 @@ AddressRef generate_address_ref(std::mt19937_64& rng, uint32_t max_operand_value
5151
5252std::vector<FuzzInstruction> generate_ecadd_instruction (std::mt19937_64& rng)
5353{
54- bool use_backfill = std::uniform_int_distribution<int >(0 , 1 )(rng) == 0 ;
54+ // 80% chance to use backfill (4 out of 5) to increase success rate
55+ bool use_backfill = std::uniform_int_distribution<int >(0 , 4 )(rng) != 0 ;
5556
5657 if (!use_backfill) {
5758 // Random mode: use existing memory values (may fail if not valid points on curve)
@@ -100,6 +101,16 @@ std::vector<FuzzInstruction> generate_ecadd_instruction(std::mt19937_64& rng)
100101 AddressRef p2_y_addr = generate_address_ref (rng, MAX_16BIT_OPERAND);
101102 AddressRef p2_inf_addr = generate_address_ref (rng, MAX_8BIT_OPERAND);
102103
104+ // Force Direct addressing so SET instructions write to the same addresses that ECADD reads from.
105+ // TODO: Implement smart backfilling for indirect addressing modes by also setting up
106+ // the pointer addresses (e.g., M[pointer_address_seed] = target_address).
107+ p1_x_addr.mode = AddressingMode::Direct;
108+ p1_y_addr.mode = AddressingMode::Direct;
109+ p1_inf_addr.mode = AddressingMode::Direct;
110+ p2_x_addr.mode = AddressingMode::Direct;
111+ p2_y_addr.mode = AddressingMode::Direct;
112+ p2_inf_addr.mode = AddressingMode::Direct;
113+
103114 backfill_point (p1, p1_x_addr, p1_y_addr, p1_inf_addr);
104115 backfill_point (p2, p2_x_addr, p2_y_addr, p2_inf_addr);
105116
@@ -143,7 +154,8 @@ FuzzInstruction generate_set_for_tag(bb::avm2::MemoryTag tag, AddressRef addr, s
143154template <typename InstructionType>
144155std::vector<FuzzInstruction> generate_alu_with_matching_tags (std::mt19937_64& rng, uint32_t max_operand)
145156{
146- bool use_backfill = std::uniform_int_distribution<int >(0 , 1 )(rng) == 0 ;
157+ // 80% chance to use backfill (4 out of 5) to increase success rate
158+ bool use_backfill = std::uniform_int_distribution<int >(0 , 4 )(rng) != 0 ;
147159
148160 if (!use_backfill) {
149161 return { InstructionType{ .a_address = generate_variable_ref (rng),
@@ -155,6 +167,12 @@ std::vector<FuzzInstruction> generate_alu_with_matching_tags(std::mt19937_64& rn
155167 AddressRef a_addr = generate_address_ref (rng, max_operand);
156168 AddressRef b_addr = generate_address_ref (rng, max_operand);
157169
170+ // Force Direct addressing so SET instructions write to the same addresses that ALU reads from.
171+ // TODO: Implement smart backfilling for indirect addressing modes by also setting up
172+ // the pointer addresses (e.g., M[pointer_address_seed] = target_address).
173+ a_addr.mode = AddressingMode::Direct;
174+ b_addr.mode = AddressingMode::Direct;
175+
158176 std::vector<FuzzInstruction> instructions;
159177 instructions.push_back (generate_set_for_tag (tag, a_addr, rng));
160178 instructions.push_back (generate_set_for_tag (tag, b_addr, rng));
@@ -168,7 +186,8 @@ std::vector<FuzzInstruction> generate_alu_with_matching_tags(std::mt19937_64& rn
168186template <typename InstructionType>
169187std::vector<FuzzInstruction> generate_alu_with_matching_tags_not_ff (std::mt19937_64& rng, uint32_t max_operand)
170188{
171- bool use_backfill = std::uniform_int_distribution<int >(0 , 1 )(rng) == 0 ;
189+ // 80% chance to use backfill (4 out of 5) to increase success rate
190+ bool use_backfill = std::uniform_int_distribution<int >(0 , 4 )(rng) != 0 ;
172191
173192 if (!use_backfill) {
174193 return { InstructionType{ .a_address = generate_variable_ref (rng),
@@ -186,6 +205,12 @@ std::vector<FuzzInstruction> generate_alu_with_matching_tags_not_ff(std::mt19937
186205 AddressRef a_addr = generate_address_ref (rng, max_operand);
187206 AddressRef b_addr = generate_address_ref (rng, max_operand);
188207
208+ // Force Direct addressing so SET instructions write to the same addresses that ALU reads from.
209+ // TODO: Implement smart backfilling for indirect addressing modes by also setting up
210+ // the pointer addresses (e.g., M[pointer_address_seed] = target_address).
211+ a_addr.mode = AddressingMode::Direct;
212+ b_addr.mode = AddressingMode::Direct;
213+
189214 std::vector<FuzzInstruction> instructions;
190215 instructions.push_back (generate_set_for_tag (tag, a_addr, rng));
191216 instructions.push_back (generate_set_for_tag (tag, b_addr, rng));
@@ -196,7 +221,8 @@ std::vector<FuzzInstruction> generate_alu_with_matching_tags_not_ff(std::mt19937
196221
197222std::vector<FuzzInstruction> generate_fdiv_instruction (std::mt19937_64& rng, uint32_t max_operand)
198223{
199- bool use_backfill = std::uniform_int_distribution<int >(0 , 1 )(rng) == 0 ;
224+ // 80% chance to use backfill (4 out of 5) to increase success rate
225+ bool use_backfill = std::uniform_int_distribution<int >(0 , 4 )(rng) != 0 ;
200226
201227 if (!use_backfill) {
202228 // Random mode: use existing memory values
@@ -221,6 +247,12 @@ std::vector<FuzzInstruction> generate_fdiv_instruction(std::mt19937_64& rng, uin
221247 AddressRef a_addr = generate_address_ref (rng, max_operand);
222248 AddressRef b_addr = generate_address_ref (rng, max_operand);
223249
250+ // Force Direct addressing so SET instructions write to the same addresses that FDIV reads from.
251+ // TODO: Implement smart backfilling for indirect addressing modes by also setting up
252+ // the pointer addresses (e.g., M[pointer_address_seed] = target_address).
253+ a_addr.mode = AddressingMode::Direct;
254+ b_addr.mode = AddressingMode::Direct;
255+
224256 // SET the dividend (a)
225257 instructions.push_back (SET_FF_Instruction{
226258 .value_tag = bb::avm2::MemoryTag::FF, .result_address = a_addr, .value = generate_nonzero_field () });
@@ -238,7 +270,8 @@ std::vector<FuzzInstruction> generate_fdiv_instruction(std::mt19937_64& rng, uin
238270
239271std::vector<FuzzInstruction> generate_keccakf_instruction (std::mt19937_64& rng)
240272{
241- bool use_backfill = std::uniform_int_distribution<int >(0 , 1 )(rng) == 0 ;
273+ // 80% chance to use backfill (4 out of 5) to increase success rate
274+ bool use_backfill = std::uniform_int_distribution<int >(0 , 4 )(rng) != 0 ;
242275 if (!use_backfill) {
243276 // Random mode
244277 return { KECCAKF1600_Instruction{ .src_address = generate_variable_ref (rng),
@@ -249,6 +282,10 @@ std::vector<FuzzInstruction> generate_keccakf_instruction(std::mt19937_64& rng)
249282 // Keccak needs to backfill 25 U64 values, these need be contiguous in memory
250283
251284 AddressRef src_address = generate_address_ref (rng, MAX_16BIT_OPERAND - 24 );
285+ // Force Direct addressing so SET instructions write to the same addresses that KECCAKF1600 reads from.
286+ // TODO: Implement smart backfilling for indirect addressing modes by also setting up
287+ // the pointer addresses (e.g., M[pointer_address_seed] = target_address).
288+ src_address.mode = AddressingMode::Direct;
252289 for (size_t i = 0 ; i < 25 ; i++) {
253290 instructions.push_back (
254291 SET_64_Instruction{ .value_tag = bb::avm2::MemoryTag::U64,
@@ -263,7 +300,8 @@ std::vector<FuzzInstruction> generate_keccakf_instruction(std::mt19937_64& rng)
263300
264301std::vector<FuzzInstruction> generate_sha256compression_instruction (std::mt19937_64& rng)
265302{
266- bool use_backfill = std::uniform_int_distribution<int >(0 , 1 )(rng) == 0 ;
303+ // 80% chance to use backfill (4 out of 5) to increase success rate
304+ bool use_backfill = std::uniform_int_distribution<int >(0 , 4 )(rng) != 0 ;
267305 if (!use_backfill) {
268306 // Random mode
269307 return { SHA256COMPRESSION_Instruction{ .state_address = generate_variable_ref (rng),
@@ -277,6 +315,10 @@ std::vector<FuzzInstruction> generate_sha256compression_instruction(std::mt19937
277315
278316 // Generate state address (8 contiguous U32 values)
279317 AddressRef state_address = generate_address_ref (rng, MAX_16BIT_OPERAND - 7 );
318+ // Force Direct addressing so SET instructions write to the same addresses that SHA256COMPRESSION reads from.
319+ // TODO: Implement smart backfilling for indirect addressing modes by also setting up
320+ // the pointer addresses (e.g., M[pointer_address_seed] = target_address).
321+ state_address.mode = AddressingMode::Direct;
280322 for (size_t i = 0 ; i < 8 ; i++) {
281323 instructions.push_back (SET_32_Instruction{
282324 .value_tag = bb::avm2::MemoryTag::U32,
@@ -287,6 +329,7 @@ std::vector<FuzzInstruction> generate_sha256compression_instruction(std::mt19937
287329
288330 // Generate input address (16 contiguous U32 values)
289331 AddressRef input_address = generate_address_ref (rng, MAX_16BIT_OPERAND - 15 );
332+ input_address.mode = AddressingMode::Direct;
290333 for (size_t i = 0 ; i < 16 ; i++) {
291334 instructions.push_back (SET_32_Instruction{
292335 .value_tag = bb::avm2::MemoryTag::U32,
@@ -304,7 +347,8 @@ std::vector<FuzzInstruction> generate_sha256compression_instruction(std::mt19937
304347
305348std::vector<FuzzInstruction> generate_toradixbe_instruction (std::mt19937_64& rng)
306349{
307- bool use_backfill = std::uniform_int_distribution<int >(0 , 1 )(rng) == 0 ;
350+ // 80% chance to use backfill (4 out of 5) to increase success rate
351+ bool use_backfill = std::uniform_int_distribution<int >(0 , 4 )(rng) != 0 ;
308352 if (!use_backfill) {
309353 // Random mode
310354 return { TORADIXBE_Instruction{ .value_address = generate_variable_ref (rng),
@@ -324,6 +368,14 @@ std::vector<FuzzInstruction> generate_toradixbe_instruction(std::mt19937_64& rng
324368 AddressRef num_limbs_addr = generate_address_ref (rng, MAX_16BIT_OPERAND);
325369 AddressRef output_bits_addr = generate_address_ref (rng, MAX_8BIT_OPERAND);
326370
371+ // Force Direct addressing so SET instructions write to the same addresses that TORADIXBE reads from.
372+ // TODO: Implement smart backfilling for indirect addressing modes by also setting up
373+ // the pointer addresses (e.g., M[pointer_address_seed] = target_address).
374+ value_addr.mode = AddressingMode::Direct;
375+ radix_addr.mode = AddressingMode::Direct;
376+ num_limbs_addr.mode = AddressingMode::Direct;
377+ output_bits_addr.mode = AddressingMode::Direct;
378+
327379 // SET the radix (U32) - pick radix between 2 and 256
328380 uint32_t radix = std::uniform_int_distribution<uint32_t >(2 , 256 )(rng);
329381 instructions.push_back (
@@ -360,6 +412,47 @@ std::vector<FuzzInstruction> generate_toradixbe_instruction(std::mt19937_64& rng
360412 return instructions;
361413}
362414
415+ // A better way in the future is to pass in a vector of possible slots that have been written to,
416+ // this would allow us to supply external world state info.
417+ std::vector<FuzzInstruction> generate_sload_instruction (std::mt19937_64& rng)
418+ {
419+ // 80% chance to use backfill (4 out of 5) to increase success rate
420+ bool use_backfill = std::uniform_int_distribution<int >(0 , 4 )(rng) != 0 ;
421+
422+ if (!use_backfill) {
423+ // Random mode: requires at least one prior SSTORE to have been processed
424+ return { SLOAD_Instruction{ .slot_index = generate_random_uint16 (rng),
425+ .slot_address = generate_address_ref (rng, MAX_16BIT_OPERAND),
426+ .result_address = generate_address_ref (rng, MAX_16BIT_OPERAND) } };
427+ }
428+
429+ // Backfill mode: generate SSTORE first to ensure storage_addresses is non-empty
430+ // This guarantees SLOAD will find a valid slot (get_slot uses modulo on non-empty vector)
431+ std::vector<FuzzInstruction> instructions;
432+ instructions.reserve (3 );
433+
434+ AddressRef sstore_src = generate_address_ref (rng, MAX_16BIT_OPERAND);
435+ // Force Direct addressing so SET writes to the same address that SSTORE reads from.
436+ // TODO: Implement smart backfilling for indirect addressing modes.
437+ sstore_src.mode = AddressingMode::Direct;
438+
439+ // SET a value to store
440+ instructions.push_back (SET_FF_Instruction{
441+ .value_tag = bb::avm2::MemoryTag::FF, .result_address = sstore_src, .value = generate_random_field (rng) });
442+
443+ // SSTORE - appends to storage_addresses in memory_manager
444+ instructions.push_back (SSTORE_Instruction{ .src_address = sstore_src,
445+ .result_address = generate_address_ref (rng, MAX_16BIT_OPERAND),
446+ .slot = generate_random_field (rng) });
447+
448+ // SLOAD - now guaranteed to succeed (storage_addresses not empty, get_slot uses modulo)
449+ instructions.push_back (SLOAD_Instruction{ .slot_index = generate_random_uint16 (rng),
450+ .slot_address = generate_address_ref (rng, MAX_16BIT_OPERAND),
451+ .result_address = generate_address_ref (rng, MAX_16BIT_OPERAND) });
452+
453+ return instructions;
454+ }
455+
363456std::vector<FuzzInstruction> generate_instruction (std::mt19937_64& rng)
364457{
365458 InstructionGenerationOptions option = BASIC_INSTRUCTION_GENERATION_CONFIGURATION.select (rng);
@@ -494,9 +587,7 @@ std::vector<FuzzInstruction> generate_instruction(std::mt19937_64& rng)
494587 .result_address = generate_address_ref (rng, MAX_16BIT_OPERAND),
495588 .slot = generate_random_field (rng) } };
496589 case InstructionGenerationOptions::SLOAD:
497- return { SLOAD_Instruction{ .slot_index = generate_random_uint16 (rng),
498- .slot_address = generate_address_ref (rng, MAX_16BIT_OPERAND),
499- .result_address = generate_address_ref (rng, MAX_16BIT_OPERAND) } };
590+ return generate_sload_instruction (rng);
500591 case InstructionGenerationOptions::GETENVVAR:
501592 return { GETENVVAR_Instruction{ .result_address = generate_address_ref (rng, MAX_16BIT_OPERAND),
502593 .type = generate_random_uint8 (rng) } };
0 commit comments