diff --git a/avm-transpiler/src/transpile.rs b/avm-transpiler/src/transpile.rs index b02a917d874..bf98c239648 100644 --- a/avm-transpiler/src/transpile.rs +++ b/avm-transpiler/src/transpile.rs @@ -306,16 +306,12 @@ pub fn brillig_to_avm(brillig_bytecode: &[BrilligOpcode]) -> (Vec< } BrilligOpcode::Return {} => avm_instrs .push(AvmInstruction { opcode: AvmOpcode::INTERNALRETURN, ..Default::default() }), - BrilligOpcode::Stop { return_data_offset, return_data_size } => { - avm_instrs.push(AvmInstruction { - opcode: AvmOpcode::RETURN, - indirect: Some(AddressingModeBuilder::default().build()), - operands: vec![ - AvmOperand::U16 { value: *return_data_offset as u16 }, - AvmOperand::U16 { value: *return_data_size as u16 }, - ], - ..Default::default() - }); + BrilligOpcode::Stop { return_data } => { + generate_return_instruction( + &mut avm_instrs, + &return_data.pointer, + &return_data.size, + ); } BrilligOpcode::Trap { revert_data } => { generate_revert_instruction( @@ -960,6 +956,28 @@ fn generate_revert_instruction( }); } +/// Generates an AVM RETURN instruction. +fn generate_return_instruction( + avm_instrs: &mut Vec, + return_data_pointer: &MemoryAddress, + return_data_size_offset: &MemoryAddress, +) { + avm_instrs.push(AvmInstruction { + opcode: AvmOpcode::RETURN, + indirect: Some( + AddressingModeBuilder::default() + .indirect_operand(return_data_pointer) + .direct_operand(return_data_size_offset) + .build(), + ), + operands: vec![ + AvmOperand::U16 { value: return_data_pointer.to_usize() as u16 }, + AvmOperand::U16 { value: return_data_size_offset.to_usize() as u16 }, + ], + ..Default::default() + }); +} + /// Generates an AVM MOV instruction. fn generate_mov_instruction( indirect: Option, @@ -1323,25 +1341,16 @@ fn handle_return( destinations: &Vec, inputs: &Vec, ) { - assert!(inputs.len() == 1); + assert!(inputs.len() == 2); assert!(destinations.len() == 0); - let (return_data_offset, return_data_size) = match inputs[0] { - ValueOrArray::HeapArray(HeapArray { pointer, size }) => (pointer, size as u32), - _ => panic!("Return instruction's args input should be a HeapArray"), + // First arg is the size, which is ignored because it's redundant. + let (return_data_offset, return_data_size) = match inputs[1] { + ValueOrArray::HeapVector(HeapVector { pointer, size }) => (pointer, size), + _ => panic!("Revert instruction's args input should be a HeapVector"), }; - avm_instrs.push(AvmInstruction { - opcode: AvmOpcode::RETURN, - indirect: Some( - AddressingModeBuilder::default().indirect_operand(&return_data_offset).build(), - ), - operands: vec![ - AvmOperand::U16 { value: return_data_offset.to_usize() as u16 }, - AvmOperand::U16 { value: return_data_size as u16 }, - ], - ..Default::default() - }); + generate_return_instruction(avm_instrs, &return_data_offset, &return_data_size); } // #[oracle(avmOpcodeRevert)] diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/avm_recursion_constraint.test.cpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/avm_recursion_constraint.test.cpp index bb49d13b0e4..9a68ba90dee 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/avm_recursion_constraint.test.cpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/avm_recursion_constraint.test.cpp @@ -54,7 +54,8 @@ class AcirAvmRecursionConstraint : public ::testing::Test { trace_builder.op_add(0, 1, 2, 3); trace_builder.op_sub(0, 3, 2, 3); trace_builder.op_mul(0, 1, 1, 3); - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); // Passing true enables a longer trace with lookups avm_trace::inject_end_gas_values(public_inputs, trace); diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/serde/acir.hpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/serde/acir.hpp index a96a5531a0e..d8bfc79dab0 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/serde/acir.hpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/serde/acir.hpp @@ -720,8 +720,7 @@ struct BrilligOpcode { }; struct Stop { - uint64_t return_data_offset; - uint64_t return_data_size; + Program::HeapVector return_data; friend bool operator==(const Stop&, const Stop&); std::vector bincodeSerialize() const; @@ -6401,10 +6400,7 @@ namespace Program { inline bool operator==(const BrilligOpcode::Stop& lhs, const BrilligOpcode::Stop& rhs) { - if (!(lhs.return_data_offset == rhs.return_data_offset)) { - return false; - } - if (!(lhs.return_data_size == rhs.return_data_size)) { + if (!(lhs.return_data == rhs.return_data)) { return false; } return true; @@ -6434,8 +6430,7 @@ template void serde::Serializable::serialize(const Program::BrilligOpcode::Stop& obj, Serializer& serializer) { - serde::Serializable::serialize(obj.return_data_offset, serializer); - serde::Serializable::serialize(obj.return_data_size, serializer); + serde::Serializable::serialize(obj.return_data, serializer); } template <> @@ -6444,8 +6439,7 @@ Program::BrilligOpcode::Stop serde::Deserializable Deserializer& deserializer) { Program::BrilligOpcode::Stop obj; - obj.return_data_offset = serde::Deserializable::deserialize(deserializer); - obj.return_data_size = serde::Deserializable::deserialize(deserializer); + obj.return_data = serde::Deserializable::deserialize(deserializer); return obj; } diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/tests/arithmetic.test.cpp b/barretenberg/cpp/src/barretenberg/vm/avm/tests/arithmetic.test.cpp index 7f3733dd636..ebf0264e43b 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/tests/arithmetic.test.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/tests/arithmetic.test.cpp @@ -232,7 +232,8 @@ class AvmArithmeticTests : public ::testing::Test { trace_builder.op_set(0, a, addr_a, tag); trace_builder.op_set(0, b, addr_b, tag); trace_builder.op_eq(0, addr_a, addr_b, addr_c); - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); return trace_builder.finalize(); } @@ -244,7 +245,8 @@ class AvmArithmeticTests : public ::testing::Test { trace_builder.op_set(0, a, 0, tag); trace_builder.op_set(0, b, 1, tag); trace_builder.op_add(0, 0, 1, 2); - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); auto select_row = [](Row r) { return r.main_sel_op_add == FF(1); }; @@ -261,7 +263,8 @@ class AvmArithmeticTests : public ::testing::Test { trace_builder.op_set(0, a, 0, tag); trace_builder.op_set(0, b, 1, tag); trace_builder.op_sub(0, 0, 1, 2); - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); auto select_row = [](Row r) { return r.main_sel_op_sub == FF(1); }; @@ -278,7 +281,8 @@ class AvmArithmeticTests : public ::testing::Test { trace_builder.op_set(0, a, 0, tag); trace_builder.op_set(0, b, 1, tag); trace_builder.op_mul(0, 0, 1, 2); - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); auto select_row = [](Row r) { return r.main_sel_op_mul == FF(1); }; @@ -298,7 +302,8 @@ class AvmArithmeticTests : public ::testing::Test { trace_builder.op_set(0, a, 0, tag); trace_builder.op_set(0, b, 1, tag); trace_builder.op_eq(0, 0, 1, 2); - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); auto select_row = [](Row r) { return r.main_sel_op_eq == FF(1); }; @@ -406,7 +411,8 @@ TEST_F(AvmArithmeticTestsFF, addition) // Memory layout: [37,4,11,0,0,0,....] trace_builder.op_add(0, 0, 1, 4); // [37,4,11,0,41,0,....] - trace_builder.op_return(0, 0, 5); + trace_builder.op_set(0, 5, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); auto alu_row = common_validate_add(trace, FF(37), FF(4), FF(41), FF(0), FF(1), FF(4), AvmMemoryTag::FF); @@ -430,7 +436,8 @@ TEST_F(AvmArithmeticTestsFF, subtraction) // Memory layout: [8,4,17,0,0,0,....] trace_builder.op_sub(0, 2, 0, 1); // [8,9,17,0,0,0....] - trace_builder.op_return(0, 0, 3); + trace_builder.op_set(0, 3, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); auto alu_row = common_validate_sub(trace, FF(17), FF(8), FF(9), FF(2), FF(0), FF(1), AvmMemoryTag::FF); @@ -453,7 +460,8 @@ TEST_F(AvmArithmeticTestsFF, multiplication) // Memory layout: [5,0,20,0,0,0,....] trace_builder.op_mul(0, 2, 0, 1); // [5,100,20,0,0,0....] - trace_builder.op_return(0, 0, 3); + trace_builder.op_set(0, 3, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); auto alu_row_index = common_validate_mul(trace, FF(20), FF(5), FF(100), FF(2), FF(0), FF(1), AvmMemoryTag::FF); @@ -477,7 +485,8 @@ TEST_F(AvmArithmeticTestsFF, multiplicationByZero) // Memory layout: [127,0,0,0,0,0,....] trace_builder.op_mul(0, 0, 1, 2); // [127,0,0,0,0,0....] - trace_builder.op_return(0, 0, 3); + trace_builder.op_set(0, 3, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); auto alu_row_index = common_validate_mul(trace, FF(127), FF(0), FF(0), FF(0), FF(1), FF(2), AvmMemoryTag::FF); @@ -501,7 +510,8 @@ TEST_F(AvmArithmeticTestsFF, fDivision) // Memory layout: [15,315,0,0,0,0,....] trace_builder.op_fdiv(0, 1, 0, 2); // [15,315,21,0,0,0....] - trace_builder.op_return(0, 0, 3); + trace_builder.op_set(0, 3, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); // Find the first row enabling the fdiv selector @@ -529,7 +539,8 @@ TEST_F(AvmArithmeticTestsFF, fDivisionNumeratorZero) // Memory layout: [15,0,0,0,0,0,....] trace_builder.op_fdiv(0, 1, 0, 0); // [0,0,0,0,0,0....] - trace_builder.op_return(0, 0, 3); + trace_builder.op_set(0, 3, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); // Find the first row enabling the fdiv selector @@ -558,7 +569,8 @@ TEST_F(AvmArithmeticTestsFF, fDivisionByZeroError) // Memory layout: [15,0,0,0,0,0,....] trace_builder.op_fdiv(0, 0, 1, 2); // [15,0,0,0,0,0....] - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); // Find the first row enabling the fdiv selector @@ -581,7 +593,8 @@ TEST_F(AvmArithmeticTestsFF, fDivisionZeroByZeroError) { // Memory layout: [0,0,0,0,0,0,....] trace_builder.op_fdiv(0, 0, 1, 2); // [0,0,0,0,0,0....] - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); // Find the first row enabling the fdiv selector @@ -620,7 +633,8 @@ TEST_F(AvmArithmeticTestsFF, mixedOperationsWithError) trace_builder.op_fdiv(0, 3, 5, 1); // [0,23*136^(-1),45,23,68,136,0,136,136^2,0....] trace_builder.op_fdiv(0, 1, 1, 9); // [0,23*136^(-1),45,23,68,136,0,136,136^2,1,0....] trace_builder.op_fdiv(0, 9, 0, 4); // [0,23*136^(-1),45,23,1/0,136,0,136,136^2,1,0....] Error: division by 0 - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); validate_trace(std::move(trace), public_inputs, calldata, {}); @@ -637,7 +651,8 @@ TEST_F(AvmArithmeticTestsFF, equality) trace_builder.op_set(0, 2, 1, AvmMemoryTag::U32); trace_builder.op_calldata_copy(0, 0, 1, 0); trace_builder.op_eq(0, 0, 1, 2); // Memory Layout [q - 1, q - 1, 1, 0..] - trace_builder.op_return(0, 0, 3); + trace_builder.op_set(0, 3, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); auto alu_row_index = common_validate_eq(trace, elem, elem, FF(1), FF(0), FF(1), FF(2), AvmMemoryTag::FF); @@ -661,7 +676,8 @@ TEST_F(AvmArithmeticTestsFF, nonEquality) trace_builder.op_calldata_copy(0, 0, 1, 0); trace_builder.op_eq(0, 0, 1, 2); // Memory Layout [q - 1, q, 0, 0..] - trace_builder.op_return(0, 0, 3); + trace_builder.op_set(0, 3, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); auto alu_row_index = common_validate_eq(trace, elem, FF(0), FF(0), FF(0), FF(1), FF(2), AvmMemoryTag::FF); @@ -681,7 +697,8 @@ TEST_P(AvmArithmeticTestsDiv, division) trace_builder.op_set(0, a, 0, mem_tag); trace_builder.op_set(0, b, 1, mem_tag); trace_builder.op_div(0, 0, 1, 2); - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); common_validate_div(trace, a, b, output, 0, 1, 2, mem_tag); @@ -699,7 +716,8 @@ TEST_F(AvmArithmeticTests, DivisionByZeroError) trace_builder.op_set(0, 100, 0, AvmMemoryTag::U128); trace_builder.op_set(0, 0, 1, AvmMemoryTag::U128); trace_builder.op_div(0, 0, 1, 2); - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); // Find the first row enabling the div selector @@ -729,7 +747,8 @@ TEST_F(AvmArithmeticTestsU1, addition) // Memory layout: [1,0,0,0,0,....] trace_builder.op_add(0, 0, 1, 2); // [1,0,1,0,0,....] - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); auto alu_row = common_validate_add(trace, FF(1), FF(0), FF(1), FF(0), FF(1), FF(2), AvmMemoryTag::U1); @@ -749,7 +768,8 @@ TEST_F(AvmArithmeticTestsU1, additionCarry) // Memory layout: [1,1,0,0,0,....] trace_builder.op_add(0, 0, 1, 2); // [1,1,0,0,0,....] - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); auto alu_row = common_validate_add(trace, FF(1), FF(1), FF(0), FF(0), FF(1), FF(2), AvmMemoryTag::U1); @@ -769,7 +789,8 @@ TEST_F(AvmArithmeticTestsU1, subtraction) // Memory layout: [1,1,0,0,0,....] trace_builder.op_sub(0, 0, 1, 2); // [1,1,0,0,0,....] - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); auto alu_row = common_validate_sub(trace, FF(1), FF(1), FF(0), FF(0), FF(1), FF(2), AvmMemoryTag::U1); @@ -790,7 +811,8 @@ TEST_F(AvmArithmeticTestsU1, subtractionCarry) // Memory layout: [0,1,0,0,0,....] trace_builder.op_sub(0, 0, 1, 2); // [0,1,1,0,0,....] - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); auto alu_row = common_validate_sub(trace, FF(0), FF(1), FF(1), FF(0), FF(1), FF(2), AvmMemoryTag::U1); @@ -809,7 +831,8 @@ TEST_F(AvmArithmeticTestsU1, multiplication) trace_builder.op_set(0, 1, 1, AvmMemoryTag::U1); trace_builder.op_mul(0, 0, 1, 2); - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); auto alu_row_index = common_validate_mul(trace, FF(1), FF(1), FF(1), FF(0), FF(1), FF(2), AvmMemoryTag::U1); @@ -828,7 +851,8 @@ TEST_F(AvmArithmeticTestsU1, multiplicationByzero) trace_builder.op_set(0, 0, 1, AvmMemoryTag::U1); trace_builder.op_mul(0, 0, 1, 2); - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); auto alu_row_index = common_validate_mul(trace, FF(1), FF(0), FF(0), FF(0), FF(1), FF(2), AvmMemoryTag::U1); @@ -878,7 +902,8 @@ TEST_F(AvmArithmeticTestsU8, addition) // Memory layout: [62,29,0,0,0,....] trace_builder.op_add(0, 0, 1, 2); // [62,29,91,0,0,....] - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); auto alu_row = common_validate_add(trace, FF(62), FF(29), FF(91), FF(0), FF(1), FF(2), AvmMemoryTag::U8); @@ -898,7 +923,8 @@ TEST_F(AvmArithmeticTestsU8, additionCarry) // Memory layout: [159,100,0,0,0,....] trace_builder.op_add(0, 0, 1, 2); // [159,100,3,0,0,....] - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); auto alu_row = common_validate_add(trace, FF(159), FF(100), FF(3), FF(0), FF(1), FF(2), AvmMemoryTag::U8); @@ -918,7 +944,8 @@ TEST_F(AvmArithmeticTestsU8, subtraction) // Memory layout: [162,29,0,0,0,....] trace_builder.op_sub(0, 0, 1, 2); // [162,29,133,0,0,....] - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); auto alu_row = common_validate_sub(trace, FF(162), FF(29), FF(133), FF(0), FF(1), FF(2), AvmMemoryTag::U8); @@ -939,7 +966,8 @@ TEST_F(AvmArithmeticTestsU8, subtractionCarry) // Memory layout: [5,29,0,0,0,....] trace_builder.op_sub(0, 0, 1, 2); // [5,29,232,0,0,....] - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); auto alu_row = common_validate_sub(trace, FF(5), FF(29), FF(232), FF(0), FF(1), FF(2), AvmMemoryTag::U8); @@ -958,7 +986,8 @@ TEST_F(AvmArithmeticTestsU8, multiplication) trace_builder.op_set(0, 15, 1, AvmMemoryTag::U8); trace_builder.op_mul(0, 0, 1, 2); - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); auto alu_row_index = common_validate_mul(trace, FF(13), FF(15), FF(195), FF(0), FF(1), FF(2), AvmMemoryTag::U8); @@ -977,7 +1006,8 @@ TEST_F(AvmArithmeticTestsU8, multiplicationOverflow) trace_builder.op_set(0, 170, 1, AvmMemoryTag::U8); trace_builder.op_mul(0, 0, 1, 2); - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); auto alu_row_index = common_validate_mul(trace, FF(200), FF(170), FF(208), FF(0), FF(1), FF(2), AvmMemoryTag::U8); @@ -1026,7 +1056,8 @@ TEST_F(AvmArithmeticTestsU16, addition) trace_builder.op_set(0, 33005, 546, AvmMemoryTag::U16); trace_builder.op_add(0, 546, 119, 5); - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); auto alu_row = @@ -1046,7 +1077,8 @@ TEST_F(AvmArithmeticTestsU16, additionCarry) trace_builder.op_set(0, 1000, 1, AvmMemoryTag::U16); trace_builder.op_add(0, 1, 0, 0); - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); auto alu_row = @@ -1066,7 +1098,8 @@ TEST_F(AvmArithmeticTestsU16, subtraction) trace_builder.op_set(0, 33005, 546, AvmMemoryTag::U16); trace_builder.op_sub(0, 546, 119, 5); - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); auto alu_row = @@ -1087,7 +1120,8 @@ TEST_F(AvmArithmeticTestsU16, subtractionCarry) trace_builder.op_set(0, 1000, 1, AvmMemoryTag::U16); trace_builder.op_sub(0, 1, 0, 0); - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); auto alu_row = @@ -1107,7 +1141,8 @@ TEST_F(AvmArithmeticTestsU16, multiplication) trace_builder.op_set(0, 245, 1, AvmMemoryTag::U16); trace_builder.op_mul(0, 0, 1, 2); - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); auto alu_index = common_validate_mul(trace, FF(200), FF(245), FF(49000), FF(0), FF(1), FF(2), AvmMemoryTag::U16); @@ -1126,7 +1161,8 @@ TEST_F(AvmArithmeticTestsU16, multiplicationOverflow) trace_builder.op_set(0, 1024, 1, AvmMemoryTag::U16); trace_builder.op_mul(0, 0, 1, 2); - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); auto alu_index = common_validate_mul(trace, FF(512), FF(1024), FF(0), FF(0), FF(1), FF(2), AvmMemoryTag::U16); @@ -1175,7 +1211,8 @@ TEST_F(AvmArithmeticTestsU32, addition) trace_builder.op_set(0, 1234567891, 9, AvmMemoryTag::U32); trace_builder.op_add(0, 8, 9, 0); - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); auto alu_row = common_validate_add( @@ -1195,7 +1232,8 @@ TEST_F(AvmArithmeticTestsU32, additionCarry) trace_builder.op_set(0, 2293, 9, AvmMemoryTag::U32); trace_builder.op_add(0, 8, 9, 0); - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); auto alu_row = @@ -1215,7 +1253,8 @@ TEST_F(AvmArithmeticTestsU32, subtraction) trace_builder.op_set(0, 1234567891, 9, AvmMemoryTag::U32); trace_builder.op_sub(0, 8, 9, 0); - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); auto alu_row = common_validate_sub( @@ -1236,7 +1275,8 @@ TEST_F(AvmArithmeticTestsU32, subtractionCarry) trace_builder.op_set(0, uint256_t(3210987654), 9, AvmMemoryTag::U32); trace_builder.op_sub(0, 9, 8, 0); - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); auto alu_row = common_validate_sub( @@ -1256,7 +1296,8 @@ TEST_F(AvmArithmeticTestsU32, multiplication) trace_builder.op_set(0, 11111, 1, AvmMemoryTag::U32); trace_builder.op_mul(0, 0, 1, 2); - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); auto alu_row_index = @@ -1276,7 +1317,8 @@ TEST_F(AvmArithmeticTestsU32, multiplicationOverflow) trace_builder.op_set(0, 13 << 22, 1, AvmMemoryTag::U32); trace_builder.op_mul(0, 0, 1, 2); - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); auto alu_row_index = @@ -1333,7 +1375,8 @@ TEST_F(AvmArithmeticTestsU64, addition) trace_builder.op_set(0, b, 9, AvmMemoryTag::U64); trace_builder.op_add(0, 8, 9, 9); - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); auto alu_row = common_validate_add(trace, FF(a), FF(b), FF(c), FF(8), FF(9), FF(9), AvmMemoryTag::U64); @@ -1356,7 +1399,8 @@ TEST_F(AvmArithmeticTestsU64, additionCarry) trace_builder.op_set(0, b, 1, AvmMemoryTag::U64); trace_builder.op_add(0, 0, 1, 0); - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); auto alu_row = common_validate_add(trace, FF(a), FF(b), FF(c), FF(0), FF(1), FF(0), AvmMemoryTag::U64); @@ -1379,7 +1423,8 @@ TEST_F(AvmArithmeticTestsU64, subtraction) trace_builder.op_set(0, b, 9, AvmMemoryTag::U64); trace_builder.op_sub(0, 8, 9, 9); - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); auto alu_row = common_validate_sub(trace, FF(a), FF(b), FF(c), FF(8), FF(9), FF(9), AvmMemoryTag::U64); @@ -1403,7 +1448,8 @@ TEST_F(AvmArithmeticTestsU64, subtractionCarry) trace_builder.op_set(0, b, 1, AvmMemoryTag::U64); trace_builder.op_sub(0, 0, 1, 0); - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); auto alu_row = common_validate_sub(trace, FF(a), FF(b), FF(c), FF(0), FF(1), FF(0), AvmMemoryTag::U64); @@ -1422,7 +1468,8 @@ TEST_F(AvmArithmeticTestsU64, multiplication) trace_builder.op_set(0, 555444333, 1, AvmMemoryTag::U64); trace_builder.op_mul(0, 0, 1, 2); - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); auto alu_row_index = common_validate_mul( @@ -1446,7 +1493,8 @@ TEST_F(AvmArithmeticTestsU64, multiplicationOverflow) trace_builder.op_set(0, b, 1, AvmMemoryTag::U64); trace_builder.op_mul(0, 0, 1, 2); - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); auto alu_row_index = common_validate_mul(trace, FF(a), FF(b), FF(1), FF(0), FF(1), FF(2), AvmMemoryTag::U64); @@ -1500,7 +1548,8 @@ TEST_F(AvmArithmeticTestsU128, addition) trace_builder.op_set(0, b, 9, AvmMemoryTag::U128); trace_builder.op_add(0, 8, 9, 9); - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); auto alu_row = common_validate_add(trace, a, b, c, FF(8), FF(9), FF(9), AvmMemoryTag::U128); @@ -1524,7 +1573,8 @@ TEST_F(AvmArithmeticTestsU128, additionCarry) trace_builder.op_set(0, b, 9, AvmMemoryTag::U128); trace_builder.op_add(0, 8, 9, 9); - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); auto alu_row = common_validate_add(trace, a, b, c, FF(8), FF(9), FF(9), AvmMemoryTag::U128); @@ -1547,7 +1597,8 @@ TEST_F(AvmArithmeticTestsU128, subtraction) trace_builder.op_set(0, b, 9, AvmMemoryTag::U128); trace_builder.op_sub(0, 8, 9, 9); - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); auto alu_row = common_validate_sub(trace, a, b, c, FF(8), FF(9), FF(9), AvmMemoryTag::U128); @@ -1570,7 +1621,8 @@ TEST_F(AvmArithmeticTestsU128, subtractionCarry) trace_builder.op_set(0, b, 9, AvmMemoryTag::U128); trace_builder.op_sub(0, 8, 9, 9); - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); auto alu_row = common_validate_sub(trace, a, b, c, FF(8), FF(9), FF(9), AvmMemoryTag::U128); @@ -1591,7 +1643,8 @@ TEST_F(AvmArithmeticTestsU128, multiplication) FF c{ uint256_t{ 0xA7DDA0BAE60CA3A5, 0x70289AEB0, 0, 0 } }; trace_builder.op_mul(0, 0, 1, 2); - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); auto alu_row_index = common_validate_mul( @@ -1616,7 +1669,8 @@ TEST_F(AvmArithmeticTestsU128, multiplicationOverflow) trace_builder.op_set(0, b, 1, AvmMemoryTag::U128); trace_builder.op_mul(0, 0, 1, 2); - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); auto alu_row_index = common_validate_mul(trace, a, b, FF{ 8 }, FF(0), FF(1), FF(2), AvmMemoryTag::U128); @@ -1710,7 +1764,8 @@ TEST_F(AvmArithmeticNegativeTestsFF, fDivision) // Memory layout: [15,315,0,0,0,0,....] trace_builder.op_fdiv(0, 1, 0, 2); // [15,315,21,0,0,0....] - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); auto select_row = [](Row r) { return r.main_sel_op_fdiv == FF(1); }; @@ -1729,7 +1784,8 @@ TEST_F(AvmArithmeticNegativeTestsFF, fDivisionNoZeroButError) // Memory layout: [15,315,0,0,0,0,....] trace_builder.op_fdiv(0, 1, 0, 2); // [15,315,21,0,0,0....] - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); // Find the first row enabling the fdiv selector @@ -1757,7 +1813,8 @@ TEST_F(AvmArithmeticNegativeTestsFF, fDivisionByZeroNoError) // Memory layout: [15,0,0,0,0,0,....] trace_builder.op_fdiv(0, 0, 1, 2); // [15,0,0,0,0,0....] - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); // Find the first row enabling the fdiv selector @@ -1774,7 +1831,8 @@ TEST_F(AvmArithmeticNegativeTestsFF, fDivisionZeroByZeroNoError) { // Memory layout: [0,0,0,0,0,0,....] trace_builder.op_fdiv(0, 0, 1, 2); // [0,0,0,0,0,0....] - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); // Find the first row enabling the fdiv selector @@ -1794,7 +1852,8 @@ TEST_F(AvmArithmeticNegativeTestsFF, fDivisionWrongRInTag) trace_builder.op_calldata_copy(0, 0, 1, 0); // Memory layout: [18,6,0,0,0,0,....] trace_builder.op_fdiv(0, 0, 1, 2); // [18,6,3,0,0,0....] - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); // Find the first row enabling the fdiv selector @@ -1814,7 +1873,8 @@ TEST_F(AvmArithmeticNegativeTestsFF, fDivisionWrongWInTag) trace_builder.op_calldata_copy(0, 0, 1, 0); // Memory layout: [18,6,0,0,0,0,....] trace_builder.op_fdiv(0, 0, 1, 2); // [18,6,3,0,0,0....] - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); // Find the first row enabling the fdiv selector @@ -1836,8 +1896,10 @@ TEST_F(AvmArithmeticNegativeTestsFF, operationWithErrorFlag1) // Memory layout: [37,4,11,0,0,0,....] trace_builder.op_add(0, 0, 1, 4); // [37,4,11,0,41,0,....] - trace_builder.op_return(0, 0, 5); - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 5, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); // Find the first row enabling the addition selector @@ -1857,7 +1919,8 @@ TEST_F(AvmArithmeticNegativeTestsFF, operationWithErrorFlag2) // Memory layout: [8,4,17,0,0,0,....] trace_builder.op_sub(0, 2, 0, 1); // [8,9,17,0,0,0....] - trace_builder.op_return(0, 0, 3); + trace_builder.op_set(0, 3, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); // Find the first row enabling the subtraction selector @@ -1877,7 +1940,8 @@ TEST_F(AvmArithmeticNegativeTestsFF, operationWithErrorFlag3) // Memory layout: [5,0,20,0,0,0,....] trace_builder.op_mul(0, 2, 0, 1); // [5,100,20,0,0,0....] - trace_builder.op_return(0, 0, 3); + trace_builder.op_set(0, 3, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); // Find the first row enabling the multiplication selector @@ -1920,7 +1984,8 @@ TEST_F(AvmArithmeticNegativeTestsFF, eqOutputWrongTag) gen_trace_builder(calldata); trace_builder.op_calldata_copy(0, 0, 2, 0); trace_builder.op_eq(0, 0, 1, 2); // Memory Layout [elem, elem, 1, 0..] - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); // Find the first row enabling the eq selector @@ -2270,7 +2335,8 @@ TEST_F(AvmArithmeticNegativeTestsU128, multiplicationSecondRowNoOp) trace_builder.op_set(0, 4, 1, AvmMemoryTag::U128); trace_builder.op_mul(0, 0, 1, 2); - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); auto alu_row_index = common_validate_mul(trace, FF(3), FF(4), FF(12), FF(0), FF(1), FF(2), AvmMemoryTag::U128); diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/tests/bitwise.test.cpp b/barretenberg/cpp/src/barretenberg/vm/avm/tests/bitwise.test.cpp index 9a3b1b8b369..8ae8c6ba769 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/tests/bitwise.test.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/tests/bitwise.test.cpp @@ -361,7 +361,8 @@ class AvmBitwiseTests : public ::testing::Test { { trace_builder.op_set(0, a, 0, tag); trace_builder.op_not(0, 0, 1); - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); auto select_row = [](Row r) { return r.main_sel_op_not == FF(1); }; @@ -476,7 +477,8 @@ TEST_P(AvmBitwiseTestsNot, ParamTest) const auto [a, output] = operands; trace_builder.op_set(0, a, 0, mem_tag); trace_builder.op_not(0, 0, 1); // [1,254,0,0,....] - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); common_validate_op_not(trace, a, output, FF(0), FF(1), mem_tag); validate_trace(std::move(trace), public_inputs); @@ -493,7 +495,8 @@ TEST_P(AvmBitwiseTestsAnd, AllAndTest) trace_builder.op_set(0, a, 0, mem_tag); trace_builder.op_set(0, b, 1, mem_tag); trace_builder.op_and(0, 0, 1, 2); - trace_builder.op_return(0, 2, 1); + trace_builder.op_set(0, 1, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 2, 100); auto trace = trace_builder.finalize(); common_validate_bit_op(trace, 0, a, b, output, FF(0), FF(1), FF(2), mem_tag); @@ -510,7 +513,8 @@ TEST_P(AvmBitwiseTestsOr, AllOrTest) trace_builder.op_set(0, a, 0, mem_tag); trace_builder.op_set(0, b, 1, mem_tag); trace_builder.op_or(0, 0, 1, 2); - trace_builder.op_return(0, 2, 1); + trace_builder.op_set(0, 1, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 2, 100); auto trace = trace_builder.finalize(); common_validate_bit_op(trace, 1, a, b, output, FF(0), FF(1), FF(2), mem_tag); @@ -527,7 +531,8 @@ TEST_P(AvmBitwiseTestsXor, AllXorTest) trace_builder.op_set(0, a, 0, mem_tag); trace_builder.op_set(0, b, 1, mem_tag); trace_builder.op_xor(0, 0, 1, 2); - trace_builder.op_return(0, 2, 1); + trace_builder.op_set(0, 1, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 2, 100); auto trace = trace_builder.finalize(); common_validate_bit_op(trace, 2, a, b, output, FF(0), FF(1), FF(2), mem_tag); @@ -545,7 +550,8 @@ TEST_P(AvmBitwiseTestsShr, AllShrTest) trace_builder.op_set(0, a, 0, mem_tag); trace_builder.op_set(0, b, 1, mem_tag); trace_builder.op_shr(0, 0, 1, 2); - trace_builder.op_return(0, 2, 1); + trace_builder.op_set(0, 1, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 2, 100); auto trace = trace_builder.finalize(); common_validate_shift_op(trace, a, b, output, FF(0), FF(1), FF(2), mem_tag, true); validate_trace(std::move(trace), public_inputs, {}, { output }); @@ -562,7 +568,8 @@ TEST_P(AvmBitwiseTestsShl, AllShlTest) trace_builder.op_set(0, a, 0, mem_tag); trace_builder.op_set(0, b, 1, mem_tag); trace_builder.op_shl(0, 0, 1, 2); - trace_builder.op_return(0, 2, 1); + trace_builder.op_set(0, 1, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 2, 100); auto trace = trace_builder.finalize(); common_validate_shift_op(trace, a, b, output, FF(0), FF(1), FF(2), mem_tag, false); @@ -666,7 +673,8 @@ TEST_P(AvmBitwiseNegativeTestsAnd, AllNegativeTests) trace_builder.op_set(0, a, 0, mem_tag); trace_builder.op_set(0, b, 1, mem_tag); trace_builder.op_and(0, 0, 1, 2); - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); std::function&& select_row = [](Row r) { return r.main_sel_op_and == FF(1); }; trace = gen_mutated_trace_bit(trace, std::move(select_row), output, failure_mode); @@ -685,7 +693,8 @@ TEST_P(AvmBitwiseNegativeTestsOr, AllNegativeTests) trace_builder.op_set(0, a, 0, mem_tag); trace_builder.op_set(0, b, 1, mem_tag); trace_builder.op_or(0, 0, 1, 2); - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); std::function&& select_row = [](Row r) { return r.main_sel_op_or == FF(1); }; trace = gen_mutated_trace_bit(trace, std::move(select_row), output, failure_mode); @@ -703,7 +712,8 @@ TEST_P(AvmBitwiseNegativeTestsXor, AllNegativeTests) trace_builder.op_set(0, a, 0, mem_tag); trace_builder.op_set(0, b, 1, mem_tag); trace_builder.op_xor(0, 0, 1, 2); - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); std::function&& select_row = [](Row r) { return r.main_sel_op_xor == FF(1); }; trace = gen_mutated_trace_bit(trace, std::move(select_row), output, failure_mode); @@ -721,7 +731,8 @@ TEST_P(AvmBitwiseNegativeTestsShr, AllNegativeTests) trace_builder.op_set(0, a, 0, mem_tag); trace_builder.op_set(0, b, 1, mem_tag); trace_builder.op_shr(0, 0, 1, 2); - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); std::function&& select_row = [](Row r) { return r.main_sel_op_shr == FF(1); }; @@ -740,7 +751,8 @@ TEST_P(AvmBitwiseNegativeTestsShl, AllNegativeTests) trace_builder.op_set(0, a, 0, mem_tag); trace_builder.op_set(0, b, 1, mem_tag); trace_builder.op_shl(0, 0, 1, 2); - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); std::function&& select_row = [](Row r) { return r.main_sel_op_shl == FF(1); }; @@ -760,7 +772,8 @@ TEST_F(AvmBitwiseNegativeTestsFF, UndefinedOverFF) trace_builder.op_not(0, 0, 1); // Finally, we will have a write in row 3 of the mem_trace to copy the result // from the op_not operation. - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); // Manually update the memory tags in the relevant trace; auto trace = trace_builder.finalize(); // TODO(ilyas): When the SET opcodes applies relational constraints, this will fail diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/tests/cast.test.cpp b/barretenberg/cpp/src/barretenberg/vm/avm/tests/cast.test.cpp index 82715ee6065..6dd3bdad82f 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/tests/cast.test.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/tests/cast.test.cpp @@ -37,7 +37,8 @@ class AvmCastTests : public ::testing::Test { { trace_builder.op_set(0, uint256_t::from_uint128(a), src_address, src_tag); trace_builder.op_cast(0, src_address, dst_address, dst_tag); - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); trace = trace_builder.finalize(); gen_indices(); } @@ -187,7 +188,8 @@ TEST_F(AvmCastTests, truncationFFToU16ModMinus1) trace_builder.op_set(0, 1, 1, AvmMemoryTag::U32); trace_builder.op_calldata_copy(0, 0, 1, 0); trace_builder.op_cast(0, 0, 1, AvmMemoryTag::U16); - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); trace = trace_builder.finalize(); gen_indices(); @@ -203,7 +205,8 @@ TEST_F(AvmCastTests, truncationFFToU16ModMinus2) trace_builder.op_set(0, 1, 1, AvmMemoryTag::U32); trace_builder.op_calldata_copy(0, 0, 1, 0); trace_builder.op_cast(0, 0, 1, AvmMemoryTag::U16); - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); trace = trace_builder.finalize(); gen_indices(); @@ -227,7 +230,8 @@ TEST_F(AvmCastTests, indirectAddrTruncationU64ToU8) trace_builder.op_set(0, 11, 1, AvmMemoryTag::U32); trace_builder.op_set(0, 256'000'000'203UL, 10, AvmMemoryTag::U64); trace_builder.op_cast(3, 0, 1, AvmMemoryTag::U8); - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); trace = trace_builder.finalize(); gen_indices(); @@ -244,7 +248,8 @@ TEST_F(AvmCastTests, indirectAddrWrongResolutionU64ToU8) trace_builder.op_set(0, 11, 6, AvmMemoryTag::U32); trace_builder.op_set(0, 4234, 10, AvmMemoryTag::U64); trace_builder.op_cast(3, 5, 6, AvmMemoryTag::U8); - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); trace = trace_builder.finalize(); auto row = std::ranges::find_if(trace.begin(), trace.end(), [](Row r) { return r.main_sel_op_cast == FF(1); }); @@ -318,7 +323,8 @@ TEST_F(AvmCastNegativeTests, wrongLimbDecompositionInput) .set_range_check_required(false); trace_builder.op_calldata_copy(0, 0, 1, 0); trace_builder.op_cast(0, 0, 1, AvmMemoryTag::U16); - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); trace = trace_builder.finalize(); gen_indices(); @@ -345,7 +351,8 @@ TEST_F(AvmCastNegativeTests, wrongPSubAHi) .set_range_check_required(false); trace_builder.op_calldata_copy(0, 0, 1, 0); trace_builder.op_cast(0, 0, 1, AvmMemoryTag::U16); - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); trace = trace_builder.finalize(); gen_indices(); @@ -385,7 +392,8 @@ TEST_F(AvmCastNegativeTests, wrongRangeCheckDecompositionHi) .set_range_check_required(false); trace_builder.op_calldata_copy(0, 0, 1, 0); trace_builder.op_cast(0, 0, 1, AvmMemoryTag::U16); - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); trace = trace_builder.finalize(); gen_indices(); @@ -425,7 +433,8 @@ TEST_F(AvmCastNegativeTests, wrongCopySubHiForRangeCheck) .set_range_check_required(false); trace_builder.op_calldata_copy(0, 0, 1, 0); trace_builder.op_cast(0, 0, 1, AvmMemoryTag::U128); - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); trace = trace_builder.finalize(); gen_indices(); diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/tests/comparison.test.cpp b/barretenberg/cpp/src/barretenberg/vm/avm/tests/comparison.test.cpp index a137a0f4d0c..ff633a4d110 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/tests/comparison.test.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/tests/comparison.test.cpp @@ -122,7 +122,8 @@ TEST_P(AvmCmpTestsLT, ParamTest) trace_builder.op_set(0, b, 1, mem_tag); } trace_builder.op_lt(0, 0, 1, 2); - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); // Get the row in the avm with the LT selector set @@ -160,7 +161,8 @@ TEST_P(AvmCmpTestsLTE, ParamTest) trace_builder.op_set(0, b, 1, mem_tag); } trace_builder.op_lte(0, 0, 1, 2); - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); auto row = std::ranges::find_if(trace.begin(), trace.end(), [](Row r) { return r.main_sel_op_lte == FF(1); }); @@ -336,7 +338,8 @@ TEST_P(AvmCmpNegativeTestsLT, ParamTest) .set_range_check_required(false); trace_builder.op_calldata_copy(0, 0, 3, 0); trace_builder.op_lt(0, 0, 1, 2); - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); std::function select_row = [](Row r) { return r.main_sel_op_lt == FF(1); }; trace = gen_mutated_trace_cmp(trace, select_row, output, failure_mode, false); @@ -357,7 +360,8 @@ TEST_P(AvmCmpNegativeTestsLTE, ParamTest) .set_range_check_required(false); trace_builder.op_calldata_copy(0, 0, 3, 0); trace_builder.op_lte(0, 0, 1, 2); - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); std::function select_row = [](Row r) { return r.main_sel_op_lte == FF(1); }; trace = gen_mutated_trace_cmp(trace, select_row, output, failure_mode, true); diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/tests/control_flow.test.cpp b/barretenberg/cpp/src/barretenberg/vm/avm/tests/control_flow.test.cpp index 7238a75f52e..4ce2715058f 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/tests/control_flow.test.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/tests/control_flow.test.cpp @@ -61,14 +61,17 @@ class AvmControlFlowTests : public ::testing::Test { TEST_F(AvmControlFlowTests, simpleCall) { - uint32_t const CALL_PC = 4; + uint32_t const SET_PC = 4; + uint32_t const CALL_PC = 41; // trace_builder for the following operation // pc opcode // 0 INTERNAL_CALL(pc=4) - // 4 RETURN - trace_builder.op_internal_call(CALL_PC); - trace_builder.op_return(0, 0, 0); + // 4 SET(0, 0, 100) + // 41 RETURN + trace_builder.op_internal_call(SET_PC); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); @@ -78,7 +81,7 @@ TEST_F(AvmControlFlowTests, simpleCall) trace.begin(), trace.end(), [](Row r) { return r.main_sel_op_internal_call == FF(1); }); EXPECT_TRUE(call_row_iter != trace.end()); auto& call_row = trace.at(static_cast(call_row_iter - trace.begin())); - validate_internal_call(call_row, 0, CALL_PC, 0); + validate_internal_call(call_row, 0, SET_PC, 0); } // Check halt @@ -96,14 +99,17 @@ TEST_F(AvmControlFlowTests, simpleCall) TEST_F(AvmControlFlowTests, simpleJump) { - uint32_t const JUMP_PC = 4; + uint32_t const SET_PC = 4; + uint32_t const JUMP_PC = 41; // trace_builder for the following operation // pc opcode // 0 JUMP(pc=4) - // 4 RETURN - trace_builder.op_jump(JUMP_PC); - trace_builder.op_return(0, 0, 0); + // 4 SET(0, 0, 100) + // 41 RETURN + trace_builder.op_jump(SET_PC); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); @@ -113,7 +119,7 @@ TEST_F(AvmControlFlowTests, simpleJump) std::ranges::find_if(trace.begin(), trace.end(), [](Row r) { return r.main_sel_op_jump == FF(1); }); EXPECT_TRUE(call_row != trace.end()); EXPECT_EQ(call_row->main_pc, FF(0)); - EXPECT_EQ(call_row->main_ia, FF(JUMP_PC)); + EXPECT_EQ(call_row->main_ia, FF(SET_PC)); } // Check halt @@ -129,16 +135,20 @@ TEST_F(AvmControlFlowTests, simpleJump) TEST_F(AvmControlFlowTests, simpleCallAndReturn) { - uint32_t const CALL_PC = 20; - uint32_t const RETURN_PC = Deserialization::get_pc_increment(OpCode::INTERNALCALL); + uint32_t const SET_PC = Deserialization::get_pc_increment(OpCode::INTERNALCALL); + uint32_t const RETURN_PC = SET_PC + Deserialization::get_pc_increment(OpCode::SET_FF); + uint32_t const INTERNAL_RETURN_PC = RETURN_PC + Deserialization::get_pc_increment(OpCode::RETURN); + // trace_builder for the following operation // pc opcode - // 0 INTERNAL_CALL(pc=20) - // 20 INTERNAL_RETURN - // 5 RETURN - trace_builder.op_internal_call(CALL_PC); + // 0 INTERNAL_CALL(pc=57) + // 57 INTERNAL_RETURN + // 5 SET(0, 0, 100) + // 42 RETURN + trace_builder.op_internal_call(INTERNAL_RETURN_PC); trace_builder.op_internal_return(); - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); @@ -148,7 +158,7 @@ TEST_F(AvmControlFlowTests, simpleCallAndReturn) trace.begin(), trace.end(), [](Row r) { return r.main_sel_op_internal_call == FF(1); }); EXPECT_TRUE(call_row_iter != trace.end()); auto& call_row = trace.at(static_cast(call_row_iter - trace.begin())); - validate_internal_call(call_row, 0, CALL_PC, 0); + validate_internal_call(call_row, 0, INTERNAL_RETURN_PC, 0); } // Check return @@ -159,7 +169,7 @@ TEST_F(AvmControlFlowTests, simpleCallAndReturn) // Check that the correct result is stored at the expected memory location. EXPECT_TRUE(return_row_iter != trace.end()); auto& return_row = trace.at(static_cast(return_row_iter - trace.begin())); - validate_internal_return(return_row, CALL_PC, RETURN_PC, 1); + validate_internal_return(return_row, INTERNAL_RETURN_PC, SET_PC, 1); } // Check halt @@ -188,6 +198,7 @@ TEST_F(AvmControlFlowTests, multipleCallsAndReturns) const uint32_t NEXT_PC_2 = CALL_PC_1 + INTERNALCALL_SIZE; const uint32_t NEXT_PC_3 = CALL_PC_2 + INTERNALCALL_SIZE; const uint32_t NEXT_PC_4 = CALL_PC_2 + 2 * INTERNALCALL_SIZE; + const uint32_t RETURN_PC = NEXT_PC_1 + Deserialization::get_pc_increment(OpCode::SET_FF); // trace_builder for the following operation // pc opcode @@ -210,7 +221,8 @@ TEST_F(AvmControlFlowTests, multipleCallsAndReturns) trace_builder.op_jump(JUMP_PC_1); trace_builder.op_internal_return(); trace_builder.op_internal_return(); - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); @@ -308,7 +320,7 @@ TEST_F(AvmControlFlowTests, multipleCallsAndReturns) std::ranges::find_if(trace.begin(), trace.end(), [](Row r) { return r.main_sel_op_external_return == FF(1); }); EXPECT_TRUE(halt_row != trace.end()); - EXPECT_EQ(halt_row->main_pc, FF(NEXT_PC_1)); + EXPECT_EQ(halt_row->main_pc, FF(RETURN_PC)); validate_trace(std::move(trace), public_inputs); } diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/tests/execution.test.cpp b/barretenberg/cpp/src/barretenberg/vm/avm/tests/execution.test.cpp index ba245cbcfc0..8d77efd756d 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/tests/execution.test.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/tests/execution.test.cpp @@ -138,16 +138,21 @@ TEST_F(AvmExecutionTests, basicAddReturn) "0007" // addr a 7 "0009" // addr b 9 "0001" // addr c 1 + + to_hex(OpCode::SET_8) + // opcode SET (for return size) + "00" // Indirect flag + + to_hex(AvmMemoryTag::U32) + + "00" // val: 0 + "FF" // dst_offset=255 + to_hex(OpCode::RETURN) + // opcode RETURN "00" // Indirect flag "0000" // ret offset 0 - "0000"; // ret size 0 + "00FF"; // ret size offset 255 auto bytecode = hex_to_bytes(bytecode_hex); auto instructions = Deserialization::parse_bytecode_statically(bytecode); // 2 instructions - ASSERT_THAT(instructions, SizeIs(4)); + ASSERT_THAT(instructions, SizeIs(5)); // ADD EXPECT_THAT(instructions.at(2), @@ -157,12 +162,21 @@ TEST_F(AvmExecutionTests, basicAddReturn) VariantWith(7), VariantWith(9), VariantWith(1))))); - - // RETURN + // SET EXPECT_THAT(instructions.at(3), - AllOf(Field(&Instruction::op_code, OpCode::RETURN), + AllOf(Field(&Instruction::op_code, OpCode::SET_8), Field(&Instruction::operands, - ElementsAre(VariantWith(0), VariantWith(0), VariantWith(0))))); + ElementsAre(VariantWith(0), + VariantWith(AvmMemoryTag::U32), + VariantWith(0), + VariantWith(255))))); + + // RETURN + EXPECT_THAT( + instructions.at(4), + AllOf(Field(&Instruction::op_code, OpCode::RETURN), + Field(&Instruction::operands, + ElementsAre(VariantWith(0), VariantWith(0), VariantWith(255))))); auto trace = gen_trace_from_bytecode(bytecode); validate_trace(std::move(trace), public_inputs, {}, {}); @@ -179,22 +193,27 @@ TEST_F(AvmExecutionTests, setAndSubOpcodes) + to_hex(OpCode::SET_16) + // opcode SET "00" // Indirect flag + to_hex(AvmMemoryTag::U16) + - "9103" // val 37123 - "0033" // dst_offset 51 - + to_hex(OpCode::SUB_8) + // opcode SUB - "00" // Indirect flag - "AA" // addr a - "33" // addr b - "01" // addr c 1 + "9103" // val 37123 + "0033" // dst_offset 51 + + to_hex(OpCode::SUB_8) + // opcode SUB + "00" // Indirect flag + "AA" // addr a + "33" // addr b + "01" // addr c 1 + + to_hex(OpCode::SET_8) + // opcode SET (for return size) + "00" // Indirect flag + + to_hex(AvmMemoryTag::U32) + + "00" // val: 0 + "FF" // dst_offset=255 + to_hex(OpCode::RETURN) + // opcode RETURN "00" // Indirect flag "0000" // ret offset 0 - "0000"; // ret size 0 + "00FF"; // ret size offset 255 auto bytecode = hex_to_bytes(bytecode_hex); auto instructions = Deserialization::parse_bytecode_statically(bytecode); - ASSERT_THAT(instructions, SizeIs(4)); + ASSERT_THAT(instructions, SizeIs(5)); // SET EXPECT_THAT(instructions.at(0), @@ -256,21 +275,27 @@ TEST_F(AvmExecutionTests, powerWithMulOpcodes) "01" // addr b "01"; // addr c 1 + std::string const set_return_size_hex = to_hex(OpCode::SET_8) + // opcode SET + "00" + // Indirect flag + to_hex(AvmMemoryTag::U32) + + "00" // val + "FF"; // dst_offset + std::string const ret_hex = to_hex(OpCode::RETURN) + // opcode RETURN "00" // Indirect flag "0000" // ret offset 0 - "0000"; // ret size 0 + "00FF"; // ret size offset 255 for (int i = 0; i < 12; i++) { bytecode_hex.append(mul_hex); } - + bytecode_hex.append(set_return_size_hex); bytecode_hex.append(ret_hex); auto bytecode = hex_to_bytes(bytecode_hex); auto instructions = Deserialization::parse_bytecode_statically(bytecode); - ASSERT_THAT(instructions, SizeIs(15)); + ASSERT_THAT(instructions, SizeIs(16)); // MUL first pos EXPECT_THAT(instructions.at(2), @@ -290,11 +315,21 @@ TEST_F(AvmExecutionTests, powerWithMulOpcodes) VariantWith(1), VariantWith(1))))); - // RETURN + // SET EXPECT_THAT(instructions.at(14), - AllOf(Field(&Instruction::op_code, OpCode::RETURN), + AllOf(Field(&Instruction::op_code, OpCode::SET_8), Field(&Instruction::operands, - ElementsAre(VariantWith(0), VariantWith(0), VariantWith(0))))); + ElementsAre(VariantWith(0), + VariantWith(AvmMemoryTag::U32), + VariantWith(0), + VariantWith(255))))); + + // RETURN + EXPECT_THAT( + instructions.at(15), + AllOf(Field(&Instruction::op_code, OpCode::RETURN), + Field(&Instruction::operands, + ElementsAre(VariantWith(0), VariantWith(0), VariantWith(255))))); auto trace = gen_trace_from_bytecode(bytecode); @@ -317,9 +352,9 @@ TEST_F(AvmExecutionTests, powerWithMulOpcodes) // CALL internal routine // ADD M[4] with M[7] and output in M[9] // Internal routine bytecode is at the end. -// Bytecode layout: SET_32 INTERNAL_CALL ADD_16 RETURN SET_32 INTERNAL_RETURN -// Instr. Index 0 1 2 3 4 5 -// PC Index 0 9 14 22 28 37 +// Bytecode layout: SET_32 INTERNAL_CALL ADD_16 SET_8 RETURN SET_32 INTERNAL_RETURN +// Instr. Index 0 1 2 3 4 5 6 +// PC Index 0 9 14 22 27 33 42 TEST_F(AvmExecutionTests, simpleInternalCall) { std::string bytecode_hex = to_hex(OpCode::SET_32) + // opcode SET @@ -328,19 +363,24 @@ TEST_F(AvmExecutionTests, simpleInternalCall) "0D3D2518" // val 222111000 = 0xD3D2518 "0004" // dst_offset 4 + to_hex(OpCode::INTERNALCALL) + // opcode INTERNALCALL - "0000001C" // jmp_dest 28 + "00000021" // jmp_dest 33 + to_hex(OpCode::ADD_16) + // opcode ADD "00" // Indirect flag "0004" // addr a 4 "0007" // addr b 7 "0009" // addr c9 - + to_hex(OpCode::RETURN) + // opcode RETURN - "00" // Indirect flag - "0000" // ret offset 0 - "0000" // ret size 0 - + to_hex(OpCode::SET_32) + // opcode SET + + to_hex(OpCode::SET_8) + // opcode SET (for return size) "00" // Indirect flag + to_hex(AvmMemoryTag::U32) + + "00" // val: 0 + "FF" // dst_offset=255 + + to_hex(OpCode::RETURN) + // opcode RETURN + "00" // Indirect flag + "0000" // ret offset 0 + "00FF" // ret size offset 255 + + to_hex(OpCode::SET_32) + // opcode SET + "00" // Indirect flag + + to_hex(AvmMemoryTag::U32) + "075BCD15" // val 123456789 = 0x75BCD15 "0007" // dst_offset 7 + to_hex(OpCode::INTERNALRETURN) // opcode INTERNALRETURN @@ -349,24 +389,24 @@ TEST_F(AvmExecutionTests, simpleInternalCall) auto bytecode = hex_to_bytes(bytecode_hex); auto instructions = Deserialization::parse_bytecode_statically(bytecode); - EXPECT_THAT(instructions, SizeIs(6)); + EXPECT_THAT(instructions, SizeIs(7)); // We test parsing step for INTERNALCALL and INTERNALRETURN. // INTERNALCALL EXPECT_THAT(instructions.at(1), AllOf(Field(&Instruction::op_code, OpCode::INTERNALCALL), - Field(&Instruction::operands, ElementsAre(VariantWith(28))))); + Field(&Instruction::operands, ElementsAre(VariantWith(33))))); // INTERNALRETURN - EXPECT_EQ(instructions.at(5).op_code, OpCode::INTERNALRETURN); + EXPECT_EQ(instructions.at(6).op_code, OpCode::INTERNALRETURN); auto trace = gen_trace_from_bytecode(bytecode); // Expected sequence of PCs during execution - std::vector pc_sequence{ 0, 9, 28, 37, 14, 22 }; + std::vector pc_sequence{ 0, 9, 33, 42, 14, 22, 27 }; - for (size_t i = 0; i < 6; i++) { + for (size_t i = 0; i < 7; i++) { EXPECT_EQ(trace.at(i + 1).main_pc, pc_sequence.at(i)); } @@ -384,9 +424,9 @@ TEST_F(AvmExecutionTests, simpleInternalCall) // G: F1 SET(17,3) F2 where SET(17,3) means M[3] = 17 // MAIN: SET(4,2) SET(7,3) G // Whole execution should compute: (4 + 7) * 17 = 187 -// Bytecode layout: SET(4,2) SET(7,3) INTERNAL_CALL_G RETURN BYTECODE(F2) BYTECODE(F1) BYTECODE(G) -// Instr Index: 0 1 2 3 4 6 8 -// PC Index: 0 9 18 23 29 35 41 +// Bytecode layout: SET(4,2) SET(7,3) INTERNAL_CALL_G SET_8 RETURN BYTECODE(F2) BYTECODE(F1) BYTECODE(G) +// Instr Index: 0 1 2 3 4 5 7 9 +// PC Index: 0 9 18 23 28 34 40 46 // BYTECODE(F1): ADD(2,3,2) INTERNAL_RETURN // BYTECODE(F2): MUL(2,3,2) INTERNAL_RETURN // BYTECODE(G): INTERNAL_CALL(35) SET(17,3) INTERNAL_CALL(29) INTERNAL_RETURN @@ -409,47 +449,54 @@ TEST_F(AvmExecutionTests, nestedInternalCalls) "03" // addr b 3 "02"; // addr c 2 + std::string const set_return_size_hex = to_hex(OpCode::SET_8) + // opcode SET + "00" + // Indirect flag + to_hex(AvmMemoryTag::U32) + + "00" // val + "FF"; // dst_offset 255 + const std::string return_instruction_hex = to_hex(OpCode::RETURN) // opcode RETURN + "00" // Indirect flag "0000" // ret offset 0 - "0000"; // ret size 0 + "00FF"; // ret size offset 255 const std::string bytecode_f1 = to_hex(OpCode::ADD_8) + tag_address_arguments + to_hex(OpCode::INTERNALRETURN); const std::string bytecode_f2 = to_hex(OpCode::MUL_8) + tag_address_arguments + to_hex(OpCode::INTERNALRETURN); - const std::string bytecode_g = internalCallInstructionHex("23") + setInstructionHex("11", "03") + - internalCallInstructionHex("1D") + to_hex(OpCode::INTERNALRETURN); + const std::string bytecode_g = internalCallInstructionHex("28") + setInstructionHex("11", "03") + + internalCallInstructionHex("22") + to_hex(OpCode::INTERNALRETURN); std::string bytecode_hex = setInstructionHex("04", "02") + setInstructionHex("07", "03") + - internalCallInstructionHex("29") + return_instruction_hex + bytecode_f2 + bytecode_f1 + - bytecode_g; + internalCallInstructionHex("2E") + set_return_size_hex + return_instruction_hex + + bytecode_f2 + bytecode_f1 + bytecode_g; auto bytecode = hex_to_bytes(bytecode_hex); auto instructions = Deserialization::parse_bytecode_statically(bytecode); - ASSERT_THAT(instructions, SizeIs(12)); + ASSERT_THAT(instructions, SizeIs(13)); // Expected sequence of opcodes - std::vector const opcode_sequence{ OpCode::SET_32, OpCode::SET_32, OpCode::INTERNALCALL, - OpCode::RETURN, OpCode::MUL_8, OpCode::INTERNALRETURN, - OpCode::ADD_8, OpCode::INTERNALRETURN, OpCode::INTERNALCALL, - OpCode::SET_32, OpCode::INTERNALCALL, OpCode::INTERNALRETURN }; + std::vector const opcode_sequence{ OpCode::SET_32, OpCode::SET_32, OpCode::INTERNALCALL, + OpCode::SET_8, OpCode::RETURN, OpCode::MUL_8, + OpCode::INTERNALRETURN, OpCode::ADD_8, OpCode::INTERNALRETURN, + OpCode::INTERNALCALL, OpCode::SET_32, OpCode::INTERNALCALL, + OpCode::INTERNALRETURN }; - for (size_t i = 0; i < 12; i++) { + for (size_t i = 0; i < 13; i++) { EXPECT_EQ(instructions.at(i).op_code, opcode_sequence.at(i)); } auto trace = gen_trace_from_bytecode(bytecode); // Expected sequence of PCs during execution - std::vector pc_sequence{ 0, 9, 18, 41, 35, 40, 46, 55, 29, 34, 60, 23 }; + std::vector pc_sequence{ 0, 9, 18, 46, 40, 45, 51, 60, 34, 39, 65, 23, 28 }; - for (size_t i = 0; i < 12; i++) { + for (size_t i = 0; i < 13; i++) { EXPECT_EQ(trace.at(i + 1).main_pc, pc_sequence.at(i)); } // Find the first row enabling the multiplication selector. auto row = std::ranges::find_if(trace.begin(), trace.end(), [](Row r) { return r.main_sel_op_mul == 1; }); EXPECT_EQ(row->main_ic, 187); - EXPECT_EQ(row->main_pc, 29); + EXPECT_EQ(row->main_pc, 34); validate_trace(std::move(trace), public_inputs); } @@ -458,9 +505,9 @@ TEST_F(AvmExecutionTests, nestedInternalCalls) // We test bytecode which first invokes CALLDATACOPY on a FF array of two values. // Then, a JUMP call skips a SUB opcode to land to a FDIV operation and RETURN. // Calldata: [13, 156] -// Bytecode layout: SET_8 SET_8 CALLDATACOPY JUMP SUB FDIV RETURN -// Instr. Index: 0 1 2 3 4 5 6 -// PC index: 0 5 10 18 23 28 33 +// Bytecode layout: SET_8 SET_8 CALLDATACOPY JUMP SUB FDIV SET_8 RETURN +// Instr. Index: 0 1 2 3 4 5 6 7 +// PC index: 0 5 10 18 23 28 33 38 TEST_F(AvmExecutionTests, jumpAndCalldatacopy) { std::string bytecode_hex = to_hex(OpCode::SET_8) + // opcode SET @@ -490,16 +537,21 @@ TEST_F(AvmExecutionTests, jumpAndCalldatacopy) "0B" // addr 11 "0A" // addr 10 "01" // addr c 1 (156 / 13 = 12) - + to_hex(OpCode::RETURN) + // opcode RETURN + + to_hex(OpCode::SET_8) + // opcode SET (for return size) "00" // Indirect flag - "0000" // ret offset 0 - "0000" // ret size 0 + + to_hex(AvmMemoryTag::U32) + + "00" // val: 0 + "FF" // dst_offset=255 + + to_hex(OpCode::RETURN) + // opcode RETURN + "00" // Indirect flag + "0000" // ret offset 0 + "00FF" // ret size offset 255 ; auto bytecode = hex_to_bytes(bytecode_hex); auto instructions = Deserialization::parse_bytecode_statically(bytecode); - ASSERT_THAT(instructions, SizeIs(7)); + ASSERT_THAT(instructions, SizeIs(8)); // We test parsing steps for CALLDATACOPY and JUMP. @@ -522,9 +574,9 @@ TEST_F(AvmExecutionTests, jumpAndCalldatacopy) auto trace = gen_trace(bytecode, std::vector{ 13, 156 }, public_inputs_vec, returndata, execution_hints); // Expected sequence of PCs during execution - std::vector pc_sequence{ 0, 5, 10, 18, 28, 33 }; + std::vector pc_sequence{ 0, 5, 10, 18, 28, 33, 38 }; - for (size_t i = 0; i < 6; i++) { + for (size_t i = 0; i < 7; i++) { EXPECT_EQ(trace.at(i + 1).main_pc, pc_sequence.at(i)); } @@ -547,9 +599,9 @@ TEST_F(AvmExecutionTests, jumpAndCalldatacopy) // Then, we set value 20 (UINT16) at memory offset 101. // Then, a JUMPI call is performed. Depending of the conditional value, the next opcode (ADD) is // omitted or not, i.e., we jump to the subsequent opcode MUL. -// Bytecode layout: SET SET CALLDATACOPY SET JUMPI ADD MUL RETURN -// Instr. Index: 0 1 2 3 4 5 6 7 -// PC Index: 0 5 10 18 23 31 39 44 +// Bytecode layout: SET SET CALLDATACOPY SET JUMPI ADD MUL SET_8 RETURN +// Instr. Index: 0 1 2 3 4 5 6 7 8 +// PC Index: 0 5 10 18 23 31 39 44 49 // We test this bytecode with two calldatacopy inputs: {9873123} and {0}. TEST_F(AvmExecutionTests, jumpiAndCalldatacopy) { @@ -587,16 +639,21 @@ TEST_F(AvmExecutionTests, jumpiAndCalldatacopy) "65" // addr 101 "65" // addr 101 "66" // output of MUL addr 102 - + to_hex(OpCode::RETURN) + // opcode RETURN + + to_hex(OpCode::SET_8) + // opcode SET (for return size) "00" // Indirect flag - "0000" // ret offset 0 - "0000" // ret size 0 + + to_hex(AvmMemoryTag::U32) + + "00" // val: 0 + "FF" // dst_offset=255 + + to_hex(OpCode::RETURN) + // opcode RETURN + "00" // Indirect flag + "0000" // ret offset 0 + "00FF" // ret size offset 255 ; auto bytecode = hex_to_bytes(bytecode_hex); auto instructions = Deserialization::parse_bytecode_statically(bytecode); - ASSERT_THAT(instructions, SizeIs(8)); + ASSERT_THAT(instructions, SizeIs(9)); // We test parsing of JUMPI. @@ -613,15 +670,15 @@ TEST_F(AvmExecutionTests, jumpiAndCalldatacopy) auto trace_no_jump = gen_trace(bytecode, std::vector{ 0 }, public_inputs_vec, returndata, execution_hints); // Expected sequence of PCs during execution with jump - std::vector pc_sequence_jump{ 0, 5, 10, 18, 23, 39, 44 }; + std::vector pc_sequence_jump{ 0, 5, 10, 18, 23, 39, 44, 49 }; // Expected sequence of PCs during execution without jump - std::vector pc_sequence_no_jump{ 0, 5, 10, 18, 23, 31, 39, 44 }; + std::vector pc_sequence_no_jump{ 0, 5, 10, 18, 23, 31, 39, 44, 49 }; - for (size_t i = 0; i < 7; i++) { + for (size_t i = 0; i < 8; i++) { EXPECT_EQ(trace_jump.at(i + 1).main_pc, pc_sequence_jump.at(i)); } - for (size_t i = 0; i < 8; i++) { + for (size_t i = 0; i < 9; i++) { EXPECT_EQ(trace_no_jump.at(i + 1).main_pc, pc_sequence_no_jump.at(i)); } @@ -636,21 +693,26 @@ TEST_F(AvmExecutionTests, movOpcode) std::string bytecode_hex = to_hex(OpCode::SET_8) + // opcode SET "00" // Indirect flag + to_hex(AvmMemoryTag::U8) + - "13" // val 19 - "AB" // dst_offset 171 - + to_hex(OpCode::MOV_8) + // opcode MOV - "00" // Indirect flag - "AB" // src_offset 171 - "21" // dst_offset 33 + "13" // val 19 + "AB" // dst_offset 171 + + to_hex(OpCode::MOV_8) + // opcode MOV + "00" // Indirect flag + "AB" // src_offset 171 + "21" // dst_offset 33 + + to_hex(OpCode::SET_8) + // opcode SET (for return size) + "00" // Indirect flag + + to_hex(AvmMemoryTag::U32) + + "00" // val: 0 + "FF" // dst_offset=255 + to_hex(OpCode::RETURN) + // opcode RETURN "00" // Indirect flag "0000" // ret offset 0 - "0000"; // ret size 0 + "00FF"; // ret size offset 255 auto bytecode = hex_to_bytes(bytecode_hex); auto instructions = Deserialization::parse_bytecode_statically(bytecode); - ASSERT_THAT(instructions, SizeIs(3)); + ASSERT_THAT(instructions, SizeIs(4)); // SET EXPECT_THAT(instructions.at(0), @@ -694,21 +756,26 @@ TEST_F(AvmExecutionTests, indMovOpcode) + to_hex(OpCode::SET_8) + // opcode SET "00" // Indirect flag + to_hex(AvmMemoryTag::U8) + - "FF" // val 255 - "0A" // dst_offset 10 - + to_hex(OpCode::MOV_8) + // opcode MOV - "01" // Indirect flag - "01" // src_offset 1 --> direct offset 10 - "02" // dst_offset 2 --> direct offset 11 + "FF" // val 255 + "0A" // dst_offset 10 + + to_hex(OpCode::MOV_8) + // opcode MOV + "01" // Indirect flag + "01" // src_offset 1 --> direct offset 10 + "02" // dst_offset 2 --> direct offset 11 + + to_hex(OpCode::SET_8) + // opcode SET (for return size) + "00" // Indirect flag + + to_hex(AvmMemoryTag::U32) + + "00" // val: 0 + "FF" // dst_offset=255 + to_hex(OpCode::RETURN) + // opcode RETURN "00" // Indirect flag "0000" // ret offset 0 - "0000"; // ret size 0 + "00FF"; // ret size offset 255 auto bytecode = hex_to_bytes(bytecode_hex); auto instructions = Deserialization::parse_bytecode_statically(bytecode); - ASSERT_THAT(instructions, SizeIs(5)); + ASSERT_THAT(instructions, SizeIs(6)); // MOV EXPECT_THAT(instructions.at(3), @@ -737,17 +804,22 @@ TEST_F(AvmExecutionTests, setAndCastOpcodes) + to_hex(OpCode::CAST_8) + // opcode CAST "00" // Indirect flag + to_hex(AvmMemoryTag::U8) + - "11" // addr a - "12" // addr casted a + "11" // addr a + "12" // addr casted a + + to_hex(OpCode::SET_8) + // opcode SET (for return size) + "00" // Indirect flag + + to_hex(AvmMemoryTag::U32) + + "00" // val: 0 + "FF" // dst_offset=255 + to_hex(OpCode::RETURN) + // opcode RETURN "00" // Indirect flag "0000" // ret offset 0 - "0000"; // ret size 0 + "00FF"; // ret size offset 255 auto bytecode = hex_to_bytes(bytecode_hex); auto instructions = Deserialization::parse_bytecode_statically(bytecode); - ASSERT_THAT(instructions, SizeIs(3)); + ASSERT_THAT(instructions, SizeIs(4)); // SUB EXPECT_THAT(instructions.at(1), @@ -807,10 +879,15 @@ TEST_F(AvmExecutionTests, toRadixBeOpcodeBytes) "0080" // radix_offset 80 (direct) "0100" // limbs: 256 "00" // output_bits: false - + to_hex(OpCode::RETURN) + // opcode RETURN + + to_hex(OpCode::SET_16) + // opcode SET (for return size) "00" // Indirect flag - "0005" // ret offset 0 - "0100"; // ret size 0 + + to_hex(AvmMemoryTag::U32) + + "0100" // val: 256 + "0200" + // dst_offset=512 + to_hex(OpCode::RETURN) + // opcode RETURN + "00" // Indirect flag + "0005" // ret offset 5 + "0200"; // ret size offset 512 auto bytecode = hex_to_bytes(bytecode_hex); auto instructions = Deserialization::parse_bytecode_statically(bytecode); @@ -876,10 +953,15 @@ TEST_F(AvmExecutionTests, toRadixBeOpcodeBitsMode) "0080" // radix_offset 80 (direct) "0100" // limbs: 256 "01" // output_bits: true - + to_hex(OpCode::RETURN) + // opcode RETURN + + to_hex(OpCode::SET_16) + // opcode SET (for return size) "00" // Indirect flag - "0005" // ret offset 0 - "0100"; // ret size 0 + + to_hex(AvmMemoryTag::U32) + + "0100" // val: 256 + "0200" + // dst_offset=512 + to_hex(OpCode::RETURN) + // opcode RETURN + "00" // Indirect flag + "0005" // ret offset 5 + "0200"; // ret size offset 512 auto bytecode = hex_to_bytes(bytecode_hex); auto instructions = Deserialization::parse_bytecode_statically(bytecode); @@ -948,10 +1030,15 @@ TEST_F(AvmExecutionTests, sha256CompressionOpcode) "0100" // output offset "0001" // state offset "0009" // input offset - + to_hex(OpCode::RETURN) + // opcode RETURN + + to_hex(OpCode::SET_16) + // opcode SET (for return size) "00" // Indirect flag - "0100" // ret offset 256 - "0008"; // ret size 8 + + to_hex(AvmMemoryTag::U32) + + "0008" // val: 8 + "0200" // dst_offset=512 + + to_hex(OpCode::RETURN) + // opcode RETURN + "00" // Indirect flag + "0100" // ret offset 256 + "0200"; // ret size offset 512 auto bytecode = hex_to_bytes(bytecode_hex); auto instructions = Deserialization::parse_bytecode_statically(bytecode); @@ -1010,10 +1097,15 @@ TEST_F(AvmExecutionTests, poseidon2PermutationOpCode) "03" // Indirect flag (first 2 operands indirect) "0024" // input offset (indirect 36) "0023" // output offset (indirect 35) - + to_hex(OpCode::RETURN) + // opcode RETURN + + to_hex(OpCode::SET_16) + // opcode SET (for return size) "00" // Indirect flag - "0009" // ret offset 256 - "0004"; // ret size 8 + + to_hex(AvmMemoryTag::U32) + + "0004" // val: 4 + "0200" // dst_offset=512 + + to_hex(OpCode::RETURN) + // opcode RETURN + "00" // Indirect flag + "0009" // ret offset 256 + "0200"; // ret size offset 512 auto bytecode = hex_to_bytes(bytecode_hex); auto instructions = Deserialization::parse_bytecode_statically(bytecode); @@ -1083,10 +1175,15 @@ TEST_F(AvmExecutionTests, keccakf1600OpCode) "03" // Indirect flag (first 2 operands indirect) "0023" // output offset (indirect 35) "0024" // input offset (indirect 36) - + to_hex(OpCode::RETURN) + // opcode RETURN + + to_hex(OpCode::SET_16) + // opcode SET (for return size) "00" // Indirect flag - "0100" // ret offset 256 - "0019"; // ret size 25 + + to_hex(AvmMemoryTag::U32) + + "0019" // val: 25 + "0200" // dst_offset=512 + + to_hex(OpCode::RETURN) + // opcode RETURN + "00" // Indirect flag + "0100" // ret offset 256 + "0200"; // ret size offset 512 auto bytecode = hex_to_bytes(bytecode_hex); auto instructions = Deserialization::parse_bytecode_statically(bytecode); @@ -1151,10 +1248,15 @@ TEST_F(AvmExecutionTests, embeddedCurveAddOpCode) "0004" // length offset (direct) "0005" // length offset (direct) "0006" // length offset (direct) + + to_hex(OpCode::SET_16) + // opcode SET (for return size) + "00" // Indirect flag + + to_hex(AvmMemoryTag::U32) + + "0003" // val: 3 + "0200" // dst_offset=512 + to_hex(OpCode::RETURN) + // opcode RETURN "00" // Indirect flag "0007" // ret offset 3 - "0003"; // ret size 1 + "0200"; // ret size offset 512 auto bytecode = hex_to_bytes(bytecode_hex); auto instructions = Deserialization::parse_bytecode_statically(bytecode); @@ -1240,10 +1342,15 @@ TEST_F(AvmExecutionTests, msmOpCode) "000e" // scalars offset "000f" // output offset "000b" // length offset + + to_hex(OpCode::SET_16) + // opcode SET (for return size) + "00" // Indirect flag + + to_hex(AvmMemoryTag::U32) + + "0003" // val: 3 + "0200" // dst_offset=512 + to_hex(OpCode::RETURN) + // opcode RETURN "00" // Indirect flag "000c" // ret offset 12 (this overwrites) - "0003"; // ret size 3 + "0200"; // ret size offset 512 auto bytecode = hex_to_bytes(bytecode_hex); auto instructions = Deserialization::parse_bytecode_statically(bytecode); @@ -1306,15 +1413,20 @@ TEST_F(AvmExecutionTests, getEnvOpcode) "00" // Indirect flag + to_hex(static_cast(EnvironmentVariable::ISSTATICCALL)) + // envvar ISSTATICCALL "000B" // dst_offset + + to_hex(OpCode::SET_16) + // opcode SET (for return size) + "00" // Indirect flag + + to_hex(AvmMemoryTag::U32) + // tag U32 + "000B" // val: 12 + "0200" // dst_offset=512 + to_hex(OpCode::RETURN) + // opcode RETURN "00" // Indirect flag "0001" // ret offset 1 - "000B"; // ret size 12 + "0200"; // ret size offset 512 auto bytecode = hex_to_bytes(bytecode_hex); auto instructions = Deserialization::parse_bytecode_statically(bytecode); - ASSERT_THAT(instructions, SizeIs(12)); + ASSERT_THAT(instructions, SizeIs(13)); // ADDRESS EXPECT_THAT(instructions.at(0), @@ -1548,16 +1660,21 @@ TEST_F(AvmExecutionTests, l2GasLeft) + to_hex(OpCode::GETENVVAR_16) + // opcode L2GASLEFT "01" // Indirect flag + to_hex(static_cast(EnvironmentVariable::L2GASLEFT)) + - "0011" // dst_offset (indirect addr: 17) + "0011" // dst_offset (indirect addr: 17) + + to_hex(OpCode::SET_8) + // opcode SET (for return size) + "00" // Indirect flag + + to_hex(AvmMemoryTag::U32) + + "00" // val: 0 + "FF" // dst_offset=255 + to_hex(OpCode::RETURN) + // opcode RETURN "00" // Indirect flag "0000" // ret offset 0 - "0000"; // ret size 0 + "00FF"; // ret size offset 255 auto bytecode = hex_to_bytes(bytecode_hex); auto instructions = Deserialization::parse_bytecode_statically(bytecode); - ASSERT_THAT(instructions, SizeIs(3)); + ASSERT_THAT(instructions, SizeIs(4)); // L2GASLEFT EXPECT_THAT(instructions.at(1), @@ -1592,16 +1709,21 @@ TEST_F(AvmExecutionTests, daGasLeft) + to_hex(OpCode::GETENVVAR_16) + // opcode DAGASLEFT "00" // Indirect flag + to_hex(static_cast(EnvironmentVariable::DAGASLEFT)) + - "0027" // dst_offset (indirect addr: 17) + "0027" // dst_offset (indirect addr: 17) + + to_hex(OpCode::SET_8) + // opcode SET (for return size) + "00" // Indirect flag + + to_hex(AvmMemoryTag::U32) + + "00" // val: 0 + "FF" // dst_offset=255 + to_hex(OpCode::RETURN) + // opcode RETURN "00" // Indirect flag "0000" // ret offset 0 - "0000"; // ret size 0 + "00FF"; // ret size offset 255 auto bytecode = hex_to_bytes(bytecode_hex); auto instructions = Deserialization::parse_bytecode_statically(bytecode); - ASSERT_THAT(instructions, SizeIs(3)); + ASSERT_THAT(instructions, SizeIs(4)); // DAGASLEFT EXPECT_THAT(instructions.at(1), @@ -1790,21 +1912,26 @@ TEST_F(AvmExecutionTests, kernelOutputStorageLoadOpcodeSimple) + to_hex(OpCode::CAST_8) + // opcode CAST (Cast set to field) "00" // Indirect flag + to_hex(AvmMemoryTag::FF) + - "01" // dst 1 - "01" // dst 1 - + to_hex(OpCode::SLOAD) + // opcode SLOAD - "00" // Indirect flag - "0001" // slot offset 1 - "0002" // write storage value to offset 2 + "01" // dst 1 + "01" // dst 1 + + to_hex(OpCode::SLOAD) + // opcode SLOAD + "00" // Indirect flag + "0001" // slot offset 1 + "0002" // write storage value to offset 2 + + to_hex(OpCode::SET_8) + // opcode SET (for return size) + "00" // Indirect flag + + to_hex(AvmMemoryTag::U32) + + "00" // val: 0 + "FF" // dst_offset=255 + to_hex(OpCode::RETURN) + // opcode RETURN "00" // Indirect flag "0000" // ret offset 0 - "0000"; // ret size 0 + "00FF"; // ret size offset 255 auto bytecode = hex_to_bytes(bytecode_hex); auto instructions = Deserialization::parse_bytecode_statically(bytecode); - ASSERT_THAT(instructions, SizeIs(4)); + ASSERT_THAT(instructions, SizeIs(5)); std::vector calldata = {}; std::vector returndata = {}; @@ -1857,10 +1984,15 @@ TEST_F(AvmExecutionTests, kernelOutputStorageStoreOpcodeSimple) "00" // Indirect flag "0001" // src offset "0003" // slot offset + + to_hex(OpCode::SET_16) + // opcode SET (for return size) + "00" // Indirect flag + + to_hex(AvmMemoryTag::U32) + // tag U32 + "0000" // val: 0 + "0200" // dst_offset=512 + to_hex(OpCode::RETURN) + // opcode RETURN "00" // Indirect flag "0000" // ret offset 0 - "0000"; // ret size 0 + "0200"; // ret size offset 512 auto bytecode = hex_to_bytes(bytecode_hex); auto instructions = Deserialization::parse_bytecode_statically(bytecode); @@ -1914,15 +2046,20 @@ TEST_F(AvmExecutionTests, kernelOutputStorageOpcodes) "00" // Indirect flag "0002" // src offset 2 (since the sload writes to 2) "0001" // slot offset is 1 + + to_hex(OpCode::SET_8) + // opcode SET (for return size) + "00" // Indirect flag + + to_hex(AvmMemoryTag::U32) + + "00" // val: 0 + "FF" // dst_offset=255 + to_hex(OpCode::RETURN) + // opcode RETURN "00" // Indirect flag "0000" // ret offset 0 - "0000"; // ret size 0 + "00FF"; // ret size offset 255 auto bytecode = hex_to_bytes(bytecode_hex); auto instructions = Deserialization::parse_bytecode_statically(bytecode); - ASSERT_THAT(instructions, SizeIs(5)); + ASSERT_THAT(instructions, SizeIs(6)); std::vector calldata = {}; std::vector returndata = {}; @@ -1995,15 +2132,20 @@ TEST_F(AvmExecutionTests, kernelOutputHashExistsOpcodes) "0001" // slot offset 1 "0002" // Lead offset 2 "0003" // value write offset 2 (exists value) + + to_hex(OpCode::SET_16) + // opcode SET (for return size) + "00" // Indirect flag + + to_hex(AvmMemoryTag::U32) + // tag U32 + "0000" // val: 0 + "0200" // dst_offset=512 + to_hex(OpCode::RETURN) + // opcode RETURN "00" // Indirect flag "0000" // ret offset 0 - "0000"; // ret size 0 + "0200"; // ret size offset 512 auto bytecode = hex_to_bytes(bytecode_hex); auto instructions = Deserialization::parse_bytecode_statically(bytecode); - ASSERT_THAT(instructions, SizeIs(6)); + ASSERT_THAT(instructions, SizeIs(7)); std::vector calldata = {}; std::vector returndata = {}; @@ -2138,10 +2280,15 @@ TEST_F(AvmExecutionTests, opCallOpcodes) "0011" // start offset (0) "0012" // ret size (2) "0100" // dst offset + + to_hex(OpCode::SET_16) + // opcode SET (for return size) + "00" // Indirect flag + + to_hex(AvmMemoryTag::U32) + // tag U32 + "0003" // val: 3 (extra read is for the success flag) + "0200" // dst_offset=512 + to_hex(OpCode::RETURN) + // opcode RETURN "00" // Indirect flag "0100" // ret offset 8 - "0003"; // ret size 3 (extra read is for the success flag) + "0200"; // ret size offset 512 auto bytecode = hex_to_bytes(bytecode_hex); auto instructions = Deserialization::parse_bytecode_statically(bytecode); @@ -2212,15 +2359,20 @@ TEST_F(AvmExecutionTests, opGetContractInstanceOpcode) "0001" // address offset "0014" // dst offset "0015" // exists offset - + to_hex(OpCode::RETURN) + // opcode RETURN - "00" // Indirect flag - "0010" // ret offset 1 - "0006"; // ret size 6 (dst & exists for all 3) + + to_hex(OpCode::SET_16) + // opcode SET (for return size) + "00" // Indirect flag + + to_hex(AvmMemoryTag::U32) + // tag U32 + "0006" // val: 6 (dst & exists for all 3) + "0200" // dst_offset=512 + + to_hex(OpCode::RETURN) + // opcode RETURN + "00" // Indirect flag + "0010" // ret offset 1 + "0200"; // ret size offset 512 auto bytecode = hex_to_bytes(bytecode_hex); auto instructions = Deserialization::parse_bytecode_statically(bytecode); - ASSERT_THAT(instructions, SizeIs(5)); + ASSERT_THAT(instructions, SizeIs(6)); std::vector const calldata{}; // alternating member value, exists bool diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/tests/gas.test.cpp b/barretenberg/cpp/src/barretenberg/vm/avm/tests/gas.test.cpp index 50fc78456ea..26cfe7468c7 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/tests/gas.test.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/tests/gas.test.cpp @@ -44,7 +44,8 @@ void test_gas(StartGas startGas, OpcodesFunc apply_opcodes, CheckFunc check_trac // We should return a value of 1 for the sender, as it exists at index 0 apply_opcodes(trace_builder); - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/tests/indirect_mem.test.cpp b/barretenberg/cpp/src/barretenberg/vm/avm/tests/indirect_mem.test.cpp index 7e3b48ffaed..e98acc28c6a 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/tests/indirect_mem.test.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/tests/indirect_mem.test.cpp @@ -42,7 +42,8 @@ TEST_F(AvmIndirectMemTests, allIndirectAdd) // All indirect flags are encoded as 7 = 1 + 2 + 4 trace_builder.op_add(7, 0, 1, 2); - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); // Find the first row enabling the addition selector @@ -91,7 +92,8 @@ TEST_F(AvmIndirectMemTests, indirectOutputSub) // The indirect flag is encoded as 4 trace_builder.op_sub(4, 50, 51, 5); - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); // Find the first row enabling the subtraction selector @@ -139,7 +141,8 @@ TEST_F(AvmIndirectMemTests, indirectInputAMul) // The indirect flag is encoded as 1 trace_builder.op_mul(1, 1000, 101, 102); - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); // Find the first row enabling the multiplication selector diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/tests/inter_table.test.cpp b/barretenberg/cpp/src/barretenberg/vm/avm/tests/inter_table.test.cpp index ac0088fbbb4..b913418b678 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/tests/inter_table.test.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/tests/inter_table.test.cpp @@ -58,7 +58,8 @@ class AvmPermMainAluNegativeTests : public AvmInterTableTests { trace_builder.op_add(0, 0, 1, 1); // 19 + 15 = 34 trace_builder.op_add(0, 0, 1, 1); // 19 + 34 = 53 trace_builder.op_mul(0, 0, 1, 2); // 19 * 53 = 1007 - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); trace = trace_builder.finalize(); @@ -153,7 +154,8 @@ class AvmRangeCheckNegativeTests : public AvmInterTableTests { trace_builder.op_set(0, a, 0, tag); trace_builder.op_set(0, b, 1, tag); trace_builder.op_add(0, 0, 1, 2); // 7 + 8 = 15 - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); trace = trace_builder.finalize(); // Find the row with addition operation and retrieve clk. @@ -404,7 +406,8 @@ class AvmPermMainMemNegativeTests : public AvmInterTableTests { trace_builder.op_set(0, a, 52, AvmMemoryTag::U8); trace_builder.op_set(0, b, 11, AvmMemoryTag::U8); trace_builder.op_sub(0, 52, 11, 55); - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); trace = trace_builder.finalize(); @@ -450,7 +453,8 @@ TEST_F(AvmPermMainMemNegativeTests, tagErrNotCopiedInMain) trace_builder.op_set(0, 32, 18, AvmMemoryTag::U128); trace_builder.op_set(0, 32, 76, AvmMemoryTag::U16); trace_builder.op_eq(0, 18, 76, 65); - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); // Find the row with equality operation and mutate the error tag. diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/tests/kernel.test.cpp b/barretenberg/cpp/src/barretenberg/vm/avm/tests/kernel.test.cpp index 2143d2419f2..219f8c668b7 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/tests/kernel.test.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/tests/kernel.test.cpp @@ -75,7 +75,8 @@ void test_kernel_lookup(bool indirect, apply_opcodes(trace_builder); - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); @@ -582,7 +583,8 @@ void negative_test_incorrect_ia_kernel_lookup(OpcodesFunc apply_opcodes, // We should return a value of 1 for the sender, as it exists at index 0 apply_opcodes(trace_builder); - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/tests/mem_opcodes.test.cpp b/barretenberg/cpp/src/barretenberg/vm/avm/tests/mem_opcodes.test.cpp index f218f873053..40a0d822d24 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/tests/mem_opcodes.test.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/tests/mem_opcodes.test.cpp @@ -56,7 +56,8 @@ class AvmMemOpcodeTests : public ::testing::Test { } trace_builder.op_mov(indirect ? 3 : 0, src_offset, dst_offset); - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); trace = trace_builder.finalize(); } @@ -218,7 +219,8 @@ TEST_F(AvmMemOpcodeTests, uninitializedValueMov) { trace_builder.op_set(0, 4, 1, AvmMemoryTag::U32); trace_builder.op_mov(0, 0, 1); - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); trace = trace_builder.finalize(); validate_mov_trace(false, 0, 0, 1, AvmMemoryTag::FF); @@ -233,7 +235,8 @@ TEST_F(AvmMemOpcodeTests, indUninitializedValueMov) trace_builder.op_set(0, 4, 1, AvmMemoryTag::U32); trace_builder.op_set(0, 5, 2, AvmMemoryTag::U32); trace_builder.op_mov(3, 2, 3); - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); trace = trace_builder.finalize(); validate_mov_trace(true, 0, 2, 3, AvmMemoryTag::FF, 5, 1); @@ -247,7 +250,8 @@ TEST_F(AvmMemOpcodeTests, indUninitializedAddrMov) trace_builder.op_set(0, 1, 3, AvmMemoryTag::U32); trace_builder.op_set(0, 4, 1, AvmMemoryTag::U32); trace_builder.op_mov(3, 2, 3); - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); trace = trace_builder.finalize(); validate_mov_trace(true, 0, 2, 3, AvmMemoryTag::FF, 0, 1, true); @@ -271,7 +275,8 @@ TEST_F(AvmMemOpcodeTests, indirectMovInvalidAddressTag) trace_builder.op_set(0, 16, 101, AvmMemoryTag::U128); // This will make the indirect load failing. trace_builder.op_set(0, 5, 15, AvmMemoryTag::FF); trace_builder.op_mov(3, 100, 101); - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); trace = trace_builder.finalize(); compute_mov_indices(true); @@ -293,7 +298,8 @@ TEST_F(AvmMemOpcodeTests, indirectMovInvalidAddressTag) TEST_F(AvmMemOpcodeTests, directSet) { trace_builder.op_set(0, 5683, 99, AvmMemoryTag::U128); - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); trace = trace_builder.finalize(); compute_index_c(1, false); @@ -321,7 +327,8 @@ TEST_F(AvmMemOpcodeTests, indirectSet) { trace_builder.op_set(0, 100, 10, AvmMemoryTag::U32); trace_builder.op_set(1, 1979, 10, AvmMemoryTag::U64); // Set 1979 at memory index 100 - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); trace = trace_builder.finalize(); // TODO(JEANMON): Turn following boolean to true once we have constraining address resolution @@ -367,7 +374,8 @@ TEST_F(AvmMemOpcodeTests, indirectSetWrongTag) trace_builder.op_set(0, 100, 10, AvmMemoryTag::U8); // The address 100 has incorrect tag U8. trace_builder.op_set(1, 1979, 10, AvmMemoryTag::U64); // Set 1979 at memory index 100 - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); trace = trace_builder.finalize(); compute_index_c(2, true); diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/tests/memory.test.cpp b/barretenberg/cpp/src/barretenberg/vm/avm/tests/memory.test.cpp index 1232d3023c4..7502b743de1 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/tests/memory.test.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/tests/memory.test.cpp @@ -43,7 +43,8 @@ TEST_F(AvmMemoryTests, mismatchedTagAddOperation) trace_builder.op_set(0, 12, 1, AvmMemoryTag::U16); trace_builder.op_add(0, 0, 1, 4); - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); // Find the first row enabling the addition selector @@ -90,7 +91,8 @@ TEST_F(AvmMemoryTests, mismatchedTagEqOperation) trace_builder.op_set(0, 5, 1, AvmMemoryTag::U16); trace_builder.op_eq(0, 0, 1, 2); - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); // Find the first row enabling the equality selector @@ -134,7 +136,8 @@ TEST_F(AvmMemoryTests, mLastAccessViolation) // Memory layout: [4,9,0,0,0,0,....] trace_builder.op_sub(0, 1, 0, 2); // [4,9,5,0,0,0.....] - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); // Find the row with subtraction operation @@ -165,14 +168,15 @@ TEST_F(AvmMemoryTests, readWriteConsistencyValViolation) // Memory layout: [4,9,0,0,0,0,....] trace_builder.op_mul(0, 1, 0, 2); // [4,9,36,0,0,0.....] - trace_builder.op_return(0, 2, 1); // Return single memory word at position 2 (36) + trace_builder.op_set(0, 1, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 2, 100); // Return single memory word at position 2 (36) auto trace = trace_builder.finalize(); // Find the row with multiplication operation auto row = std::ranges::find_if(trace.begin(), trace.end(), [](Row r) { return r.main_sel_op_mul == FF(1); }); EXPECT_TRUE(row != trace.end()); - auto clk = row->main_clk + 1; // return operation is just after the multiplication + auto clk = row->main_clk + 2; // return operation is two opcodes after the multiplication // Find the row for memory trace with last memory entry for address 2 (read for multiplication) row = std::ranges::find_if(trace.begin(), trace.end(), [clk](Row r) { @@ -195,14 +199,15 @@ TEST_F(AvmMemoryTests, readWriteConsistencyTagViolation) // Memory layout: [4,9,0,0,0,0,....] trace_builder.op_mul(0, 1, 0, 2); // [4,9,36,0,0,0.....] - trace_builder.op_return(0, 2, 1); // Return single memory word at position 2 (36) + trace_builder.op_set(0, 1, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 2, 100); // Return single memory word at position 2 (36) auto trace = trace_builder.finalize(); // Find the row with multiplication operation auto row = std::ranges::find_if(trace.begin(), trace.end(), [](Row r) { return r.main_sel_op_mul == FF(1); }); EXPECT_TRUE(row != trace.end()); - auto clk = row->main_clk + 1; // return operation is just after the multiplication + auto clk = row->main_clk + 2; // return operation is two opcodes after the multiplication // Find the row for memory trace with last memory entry for address 2 (read for multiplication) row = std::ranges::find_if(trace.begin(), trace.end(), [clk](Row r) { @@ -220,7 +225,8 @@ TEST_F(AvmMemoryTests, readWriteConsistencyTagViolation) // Testing violation that a memory read at uninitialized location must have value 0. TEST_F(AvmMemoryTests, readUninitializedMemoryViolation) { - trace_builder.op_return(0, 1, 1); // Return single memory word at position 1 + trace_builder.op_set(0, 1, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 1, 100); // Return single memory word at position 1 auto trace = trace_builder.finalize(); trace[1].mem_val = 9; @@ -238,7 +244,8 @@ TEST_F(AvmMemoryTests, mismatchedTagErrorViolation) trace_builder.op_set(0, 12, 1, AvmMemoryTag::U16); trace_builder.op_sub(0, 0, 1, 4); - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); // Find the first row enabling the subtraction selector @@ -269,7 +276,8 @@ TEST_F(AvmMemoryTests, consistentTagNoErrorViolation) trace_builder.op_set(0, 2, 1, AvmMemoryTag::U32); trace_builder.op_calldata_copy(0, 0, 1, 0); trace_builder.op_fdiv(0, 0, 1, 4); - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); // Find the first row enabling the fdiv selector @@ -298,7 +306,8 @@ TEST_F(AvmMemoryTests, noErrorTagWriteViolation) trace_builder.op_set(0, 2, 1, AvmMemoryTag::U32); trace_builder.op_calldata_copy(0, 0, 1, 0); trace_builder.op_fdiv(0, 0, 1, 4); - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); // Find the first row enabling the fdiv selector @@ -330,7 +339,8 @@ TEST_F(AvmMemoryTests, directRelativeMemory) // Addition with direct relative addressing on the 2 input operands and direct addressing on the output // indirect byte: 00011000 = 24 trace_builder.op_add(24, 10, 100, 10); - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); // Find the first row enabling the add selector @@ -361,7 +371,8 @@ TEST_F(AvmMemoryTests, indirectRelativeMemory) // Output c = a + b = 8 is stored at direct relative offset 2, i.e., address 102. // indirect byte: 00111011 = 1 + 2 + 8 + 16 + 32 = 59 trace_builder.op_add(59, 23, 47, 2); - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); // Find the first row enabling the add selector diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/tests/recursive_verifier.test.cpp b/barretenberg/cpp/src/barretenberg/vm/avm/tests/recursive_verifier.test.cpp index d6c110e3499..19eeab6d419 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/tests/recursive_verifier.test.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/tests/recursive_verifier.test.cpp @@ -53,7 +53,8 @@ class AvmRecursiveTests : public ::testing::Test { trace_builder.op_set(0, 1, 1, AvmMemoryTag::U8); trace_builder.op_set(0, 1, 2, AvmMemoryTag::U8); trace_builder.op_add(0, 1, 2, 3); - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); auto trace = trace_builder.finalize(); // Passing true enables a longer trace with lookups inject_end_gas_values(public_inputs, trace); diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/tests/slice.test.cpp b/barretenberg/cpp/src/barretenberg/vm/avm/tests/slice.test.cpp index 9a43ef6bf27..d3a3c8883ec 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/tests/slice.test.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/tests/slice.test.cpp @@ -47,7 +47,8 @@ class AvmSliceTests : public ::testing::Test { trace_builder.op_set(0, col_offset, 0, AvmMemoryTag::U32); trace_builder.op_set(0, copy_size, 1, AvmMemoryTag::U32); trace_builder.op_calldata_copy(static_cast(indirect), 0, 1, dst_offset); - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); trace = trace_builder.finalize(); } @@ -170,7 +171,8 @@ TEST_F(AvmSliceTests, twoCallsNoOverlap) trace_builder.op_set(0, 3, 1, AvmMemoryTag::U32); trace_builder.op_set(0, 2, 2, AvmMemoryTag::U32); trace_builder.op_calldata_copy(0, 1, 2, 2123); - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); trace = trace_builder.finalize(); // Main trace views of rows enabling the calldata_copy selector @@ -207,7 +209,8 @@ TEST_F(AvmSliceTests, indirectTwoCallsOverlap) trace_builder.op_set(0, 3, 3, AvmMemoryTag::U32); trace_builder.op_calldata_copy(4, 1, 3, 100); trace_builder.op_calldata_copy(4, 2, 3, 101); - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); trace = trace_builder.finalize(); // Main trace views of rows enabling the calldata_copy selector @@ -250,7 +253,8 @@ TEST_F(AvmSliceTests, indirectFailedResolution) trace_builder.op_set(0, 1, 1, AvmMemoryTag::U32); trace_builder.op_set(0, 3, 3, AvmMemoryTag::U32); trace_builder.op_calldata_copy(4, 1, 3, 100); - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); trace = trace_builder.finalize(); // Check that slice trace is empty @@ -321,7 +325,8 @@ TEST_F(AvmSliceNegativeTests, wrongCDValueInCalldataVerifier) { gen_trace_builder({ 2, 3, 4, 5, 6 }); trace_builder.op_calldata_copy(0, 1, 3, 100); - trace_builder.op_return(0, 0, 0); + trace_builder.op_set(0, 0, 100, AvmMemoryTag::U32); + trace_builder.op_return(0, 0, 100); trace = trace_builder.finalize(); validate_trace(std::move(trace), public_inputs, { 2, 3, 4, 5, 7 }, {}, false, true); diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/trace/execution.cpp b/barretenberg/cpp/src/barretenberg/vm/avm/trace/execution.cpp index 4d15050345c..0a8c36751b1 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/trace/execution.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/trace/execution.cpp @@ -289,7 +289,6 @@ std::vector Execution::gen_trace(std::vector const& calldata, uint32_t counter = 0; while ((pc = trace_builder.get_pc()) < bytecode.size()) { auto inst = Deserialization::parse(bytecode, pc); - debug("[PC:" + std::to_string(pc) + "] [IC:" + std::to_string(counter++) + "] " + inst.to_string() + " (gasLeft l2=" + std::to_string(trace_builder.get_l2_gas_left()) + ")"); diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/trace/trace.cpp b/barretenberg/cpp/src/barretenberg/vm/avm/trace/trace.cpp index 14ba70fa24a..74b63f75304 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/trace/trace.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/trace/trace.cpp @@ -2886,9 +2886,18 @@ void AvmTraceBuilder::op_static_call(uint16_t indirect, * @param ret_size The number of elements to be returned. * @return The returned memory region as a std::vector. */ -std::vector AvmTraceBuilder::op_return(uint8_t indirect, uint32_t ret_offset, uint32_t ret_size) +std::vector AvmTraceBuilder::op_return(uint8_t indirect, uint32_t ret_offset, uint32_t ret_size_offset) { auto clk = static_cast(main_trace.size()) + 1; + + // This boolean will not be a trivial constant once we re-enable constraining address resolution + bool tag_match = true; + + // Resolve operands + auto [resolved_ret_offset, resolved_ret_size_offset] = + Addressing<2>::fromWire(indirect, call_ptr).resolve({ ret_offset, ret_size_offset }, mem_trace_builder); + const auto ret_size = static_cast(unconstrained_read_from_memory(resolved_ret_size_offset)); + gas_trace_builder.constrain_gas(clk, OpCode::RETURN, ret_size); if (ret_size == 0) { @@ -2905,11 +2914,6 @@ std::vector AvmTraceBuilder::op_return(uint8_t indirect, uint32_t ret_offset return {}; } - // This boolean will not be a trivial constant once we re-enable constraining address resolution - bool tag_match = true; - - auto [resolved_ret_offset] = Addressing<1>::fromWire(indirect, call_ptr).resolve({ ret_offset }, mem_trace_builder); - // The only memory operation performed from the main trace is a possible indirect load for resolving the // direct destination offset stored in main_mem_addr_c. // All the other memory operations are triggered by the slice gadget. diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/trace/trace.hpp b/barretenberg/cpp/src/barretenberg/vm/avm/trace/trace.hpp index 76a7162ecb0..26f67e10c81 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/trace/trace.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/trace/trace.hpp @@ -162,7 +162,7 @@ class AvmTraceBuilder { uint32_t args_offset, uint32_t args_size, uint32_t success_offset); - std::vector op_return(uint8_t indirect, uint32_t ret_offset, uint32_t ret_size); + std::vector op_return(uint8_t indirect, uint32_t ret_offset, uint32_t ret_size_offset); // REVERT Opcode (that just call return under the hood for now) std::vector op_revert(uint8_t indirect, uint32_t ret_offset, uint32_t ret_size_offset); diff --git a/noir-projects/aztec-nr/aztec/src/context/public_context.nr b/noir-projects/aztec-nr/aztec/src/context/public_context.nr index 320b7b72ef1..2d0320b4da6 100644 --- a/noir-projects/aztec-nr/aztec/src/context/public_context.nr +++ b/noir-projects/aztec-nr/aztec/src/context/public_context.nr @@ -331,7 +331,7 @@ unconstrained fn returndata_copy(rdoffset: u32, copy_size: u32) -> [Field] { returndata_copy_opcode(rdoffset, copy_size) } -pub unconstrained fn avm_return(returndata: [Field; N]) { +pub unconstrained fn avm_return(returndata: [Field]) { return_opcode(returndata) } @@ -432,7 +432,7 @@ unconstrained fn returndata_size_opcode() -> u32 {} unconstrained fn returndata_copy_opcode(rdoffset: u32, copy_size: u32) -> [Field] {} #[oracle(avmOpcodeReturn)] -unconstrained fn return_opcode(returndata: [Field; N]) {} +unconstrained fn return_opcode(returndata: [Field]) {} // This opcode reverts using the exact data given. In general it should only be used // to do rethrows, where the revert data is the same as the original revert data. diff --git a/noir-projects/aztec-nr/aztec/src/macros/dispatch/mod.nr b/noir-projects/aztec-nr/aztec/src/macros/dispatch/mod.nr index 200b743ede1..956f518c19f 100644 --- a/noir-projects/aztec-nr/aztec/src/macros/dispatch/mod.nr +++ b/noir-projects/aztec-nr/aztec/src/macros/dispatch/mod.nr @@ -66,7 +66,7 @@ pub comptime fn generate_public_dispatch(m: Module) -> Quoted { } else { quote { let return_value = dep::aztec::protocol_types::traits::Serialize::serialize($call); - dep::aztec::context::public_context::avm_return(return_value); + dep::aztec::context::public_context::avm_return(return_value.as_slice()); } }; diff --git a/noir/noir-repo/acvm-repo/acir/codegen/acir.cpp b/noir/noir-repo/acvm-repo/acir/codegen/acir.cpp index 8fa471e57ba..d237f2ab3b4 100644 --- a/noir/noir-repo/acvm-repo/acir/codegen/acir.cpp +++ b/noir/noir-repo/acvm-repo/acir/codegen/acir.cpp @@ -702,8 +702,7 @@ namespace Program { }; struct Stop { - uint64_t return_data_offset; - uint64_t return_data_size; + Program::HeapVector return_data; friend bool operator==(const Stop&, const Stop&); std::vector bincodeSerialize() const; @@ -5333,8 +5332,7 @@ Program::BrilligOpcode::Trap serde::Deserializable namespace Program { inline bool operator==(const BrilligOpcode::Stop &lhs, const BrilligOpcode::Stop &rhs) { - if (!(lhs.return_data_offset == rhs.return_data_offset)) { return false; } - if (!(lhs.return_data_size == rhs.return_data_size)) { return false; } + if (!(lhs.return_data == rhs.return_data)) { return false; } return true; } @@ -5358,16 +5356,14 @@ namespace Program { template <> template void serde::Serializable::serialize(const Program::BrilligOpcode::Stop &obj, Serializer &serializer) { - serde::Serializable::serialize(obj.return_data_offset, serializer); - serde::Serializable::serialize(obj.return_data_size, serializer); + serde::Serializable::serialize(obj.return_data, serializer); } template <> template Program::BrilligOpcode::Stop serde::Deserializable::deserialize(Deserializer &deserializer) { Program::BrilligOpcode::Stop obj; - obj.return_data_offset = serde::Deserializable::deserialize(deserializer); - obj.return_data_size = serde::Deserializable::deserialize(deserializer); + obj.return_data = serde::Deserializable::deserialize(deserializer); return obj; } diff --git a/noir/noir-repo/acvm-repo/acir/tests/test_program_serialization.rs b/noir/noir-repo/acvm-repo/acir/tests/test_program_serialization.rs index 9ab153b9f61..b463d4d1fe5 100644 --- a/noir/noir-repo/acvm-repo/acir/tests/test_program_serialization.rs +++ b/noir/noir-repo/acvm-repo/acir/tests/test_program_serialization.rs @@ -20,7 +20,9 @@ use acir::{ native_types::{Expression, Witness}, }; use acir_field::{AcirField, FieldElement}; -use brillig::{BitSize, HeapArray, HeapValueType, IntegerBitSize, MemoryAddress, ValueOrArray}; +use brillig::{ + BitSize, HeapArray, HeapValueType, HeapVector, IntegerBitSize, MemoryAddress, ValueOrArray, +}; #[test] fn addition_circuit() { @@ -162,31 +164,37 @@ fn simple_brillig_foreign_call() { let w_input = Witness(1); let w_inverted = Witness(2); + let value_address = MemoryAddress::direct(0); + let zero_usize = MemoryAddress::direct(1); + let one_usize = MemoryAddress::direct(2); + let brillig_bytecode = BrilligBytecode { bytecode: vec![ brillig::Opcode::Const { - destination: MemoryAddress::direct(0), + destination: zero_usize, bit_size: BitSize::Integer(IntegerBitSize::U32), - value: FieldElement::from(1_usize), + value: FieldElement::from(0_usize), }, brillig::Opcode::Const { - destination: MemoryAddress::direct(1), + destination: one_usize, bit_size: BitSize::Integer(IntegerBitSize::U32), - value: FieldElement::from(0_usize), + value: FieldElement::from(1_usize), }, brillig::Opcode::CalldataCopy { - destination_address: MemoryAddress::direct(0), - size_address: MemoryAddress::direct(0), - offset_address: MemoryAddress::direct(1), + destination_address: value_address, + size_address: one_usize, + offset_address: zero_usize, }, brillig::Opcode::ForeignCall { function: "invert".into(), - destinations: vec![ValueOrArray::MemoryAddress(MemoryAddress::direct(0))], + destinations: vec![ValueOrArray::MemoryAddress(value_address)], destination_value_types: vec![HeapValueType::field()], - inputs: vec![ValueOrArray::MemoryAddress(MemoryAddress::direct(0))], + inputs: vec![ValueOrArray::MemoryAddress(value_address)], input_value_types: vec![HeapValueType::field()], }, - brillig::Opcode::Stop { return_data_offset: 0, return_data_size: 1 }, + brillig::Opcode::Stop { + return_data: HeapVector { pointer: zero_usize, size: one_usize }, + }, ], }; @@ -214,12 +222,12 @@ fn simple_brillig_foreign_call() { let bytes = Program::serialize_program(&program); let expected_serialization: Vec = vec![ - 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 173, 79, 73, 10, 128, 48, 12, 236, 40, 46, 5, 111, 126, - 36, 254, 192, 207, 120, 240, 226, 65, 196, 247, 91, 48, 129, 80, 186, 28, 154, 129, 144, - 201, 132, 44, 3, 247, 99, 14, 1, 230, 3, 103, 169, 53, 68, 219, 57, 83, 27, 54, 216, 237, - 34, 253, 111, 23, 19, 104, 177, 96, 76, 204, 251, 68, 191, 55, 52, 238, 163, 187, 198, 251, - 105, 114, 101, 200, 221, 37, 196, 200, 252, 188, 222, 227, 126, 80, 153, 200, 213, 57, 125, - 77, 244, 62, 112, 171, 6, 33, 119, 2, 0, 0, + 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 173, 81, 203, 10, 128, 48, 12, 179, 19, 31, 3, 111, 254, + 200, 246, 7, 254, 140, 7, 47, 30, 68, 252, 126, 39, 182, 80, 70, 182, 203, 26, 40, 73, 3, + 43, 9, 163, 238, 199, 156, 134, 88, 15, 204, 178, 107, 136, 183, 49, 135, 54, 68, 178, 187, + 21, 116, 94, 151, 11, 210, 102, 165, 152, 148, 247, 153, 255, 113, 111, 24, 214, 131, 124, + 134, 247, 227, 4, 58, 58, 208, 119, 73, 51, 178, 62, 206, 103, 191, 110, 244, 237, 250, 69, + 105, 47, 249, 43, 240, 37, 201, 11, 205, 95, 230, 87, 127, 2, 0, 0, ]; assert_eq!(bytes, expected_serialization) @@ -304,7 +312,22 @@ fn complex_brillig_foreign_call() { HeapValueType::field(), ], }, - brillig::Opcode::Stop { return_data_offset: 32, return_data_size: 5 }, + brillig::Opcode::Const { + destination: MemoryAddress::direct(0), + bit_size: BitSize::Integer(IntegerBitSize::U32), + value: FieldElement::from(32_usize), + }, + brillig::Opcode::Const { + destination: MemoryAddress::direct(1), + bit_size: BitSize::Integer(IntegerBitSize::U32), + value: FieldElement::from(5_usize), + }, + brillig::Opcode::Stop { + return_data: HeapVector { + pointer: MemoryAddress::direct(0), + size: MemoryAddress::direct(1), + }, + }, ], }; @@ -344,17 +367,17 @@ fn complex_brillig_foreign_call() { let bytes = Program::serialize_program(&program); let expected_serialization: Vec = vec![ - 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 213, 85, 93, 10, 194, 48, 12, 78, 219, 233, 54, 240, - 205, 11, 8, 122, 128, 76, 47, 176, 187, 136, 111, 138, 62, 122, 124, 45, 75, 88, 140, 197, - 9, 38, 224, 62, 24, 89, 75, 242, 229, 159, 6, 24, 208, 60, 191, 64, 255, 11, 146, 145, 100, - 190, 79, 240, 10, 214, 237, 73, 226, 111, 232, 130, 29, 23, 122, 197, 24, 103, 16, 99, 114, - 136, 17, 68, 255, 255, 176, 223, 150, 125, 49, 173, 95, 42, 236, 79, 5, 195, 126, 45, 233, - 92, 147, 108, 116, 161, 179, 81, 132, 247, 197, 147, 224, 225, 105, 149, 4, 229, 184, 183, - 73, 232, 208, 42, 191, 198, 252, 200, 197, 216, 192, 119, 249, 250, 228, 185, 71, 230, 79, - 46, 252, 216, 49, 127, 229, 212, 167, 90, 213, 75, 230, 34, 253, 174, 96, 28, 192, 227, - 245, 114, 59, 159, 238, 169, 96, 170, 205, 51, 182, 234, 188, 43, 148, 108, 138, 131, 33, - 223, 153, 79, 250, 161, 160, 63, 101, 179, 134, 113, 156, 248, 93, 123, 0, 142, 67, 44, - 107, 244, 6, 0, 0, + 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 213, 85, 205, 14, 130, 48, 12, 238, 54, 20, 136, 222, + 124, 1, 19, 125, 128, 161, 241, 238, 187, 24, 111, 26, 61, 250, 248, 186, 208, 198, 89, 26, + 56, 216, 18, 248, 18, 82, 6, 237, 215, 255, 204, 65, 139, 234, 243, 56, 124, 95, 160, 244, + 40, 211, 247, 0, 191, 32, 221, 51, 202, 248, 31, 26, 167, 199, 21, 173, 98, 244, 51, 136, + 49, 24, 196, 8, 89, 255, 39, 216, 111, 205, 190, 168, 214, 47, 8, 251, 83, 64, 187, 95, 75, + 60, 151, 40, 43, 94, 232, 100, 228, 161, 187, 120, 57, 104, 120, 86, 40, 107, 225, 191, 98, + 66, 199, 154, 249, 85, 230, 143, 84, 140, 45, 244, 231, 107, 155, 231, 33, 18, 127, 48, + 225, 143, 13, 241, 23, 70, 125, 42, 89, 189, 242, 92, 114, 191, 107, 248, 14, 224, 229, + 113, 127, 222, 174, 175, 32, 152, 114, 243, 132, 29, 59, 239, 133, 146, 13, 113, 16, 242, + 123, 166, 79, 223, 9, 250, 67, 54, 99, 141, 138, 209, 74, 156, 54, 208, 5, 249, 122, 3, 73, + 2, 62, 54, 188, 7, 0, 0, ]; assert_eq!(bytes, expected_serialization) diff --git a/noir/noir-repo/acvm-repo/acvm/tests/solver.rs b/noir/noir-repo/acvm-repo/acvm/tests/solver.rs index 2828ea3d79e..8b164b7c0f2 100644 --- a/noir/noir-repo/acvm-repo/acvm/tests/solver.rs +++ b/noir/noir-repo/acvm-repo/acvm/tests/solver.rs @@ -77,13 +77,6 @@ fn inversion_brillig_oracle_equivalence() { let w_x_plus_y = Witness(6); let w_equal_res = Witness(7); - let equal_opcode = BrilligOpcode::BinaryFieldOp { - op: BinaryFieldOp::Equals, - lhs: MemoryAddress::direct(0), - rhs: MemoryAddress::direct(1), - destination: MemoryAddress::direct(2), - }; - let opcodes = vec![ Opcode::BrilligCall { id: BrilligFunctionId(0), @@ -122,22 +115,38 @@ fn inversion_brillig_oracle_equivalence() { }), ]; + let equal_opcode = BrilligOpcode::BinaryFieldOp { + op: BinaryFieldOp::Equals, + lhs: MemoryAddress::direct(0), + rhs: MemoryAddress::direct(1), + destination: MemoryAddress::direct(2), + }; + + let zero_usize = MemoryAddress::direct(3); + let two_usize = MemoryAddress::direct(4); + let three_usize = MemoryAddress::direct(5); + let brillig_bytecode = BrilligBytecode { bytecode: vec![ BrilligOpcode::Const { - destination: MemoryAddress::direct(0), + destination: zero_usize, + bit_size: BitSize::Integer(IntegerBitSize::U32), + value: FieldElement::from(0u64), + }, + BrilligOpcode::Const { + destination: two_usize, bit_size: BitSize::Integer(IntegerBitSize::U32), value: FieldElement::from(2u64), }, BrilligOpcode::Const { - destination: MemoryAddress::direct(1), + destination: three_usize, bit_size: BitSize::Integer(IntegerBitSize::U32), - value: FieldElement::from(0u64), + value: FieldElement::from(3u64), }, BrilligOpcode::CalldataCopy { destination_address: MemoryAddress::direct(0), - size_address: MemoryAddress::direct(0), - offset_address: MemoryAddress::direct(1), + size_address: two_usize, + offset_address: zero_usize, }, equal_opcode, // Oracles are named 'foreign calls' in brillig @@ -148,7 +157,9 @@ fn inversion_brillig_oracle_equivalence() { inputs: vec![ValueOrArray::MemoryAddress(MemoryAddress::direct(0))], input_value_types: vec![HeapValueType::field()], }, - BrilligOpcode::Stop { return_data_offset: 0, return_data_size: 3 }, + BrilligOpcode::Stop { + return_data: HeapVector { pointer: zero_usize, size: three_usize }, + }, ], }; @@ -216,13 +227,6 @@ fn double_inversion_brillig_oracle() { let w_ij_oracle = Witness(10); let w_i_plus_j = Witness(11); - let equal_opcode = BrilligOpcode::BinaryFieldOp { - op: BinaryFieldOp::Equals, - lhs: MemoryAddress::direct(0), - rhs: MemoryAddress::direct(1), - destination: MemoryAddress::direct(4), - }; - let opcodes = vec![ Opcode::BrilligCall { id: BrilligFunctionId(0), @@ -268,22 +272,38 @@ fn double_inversion_brillig_oracle() { }), ]; + let zero_usize = MemoryAddress::direct(5); + let three_usize = MemoryAddress::direct(6); + let five_usize = MemoryAddress::direct(7); + + let equal_opcode = BrilligOpcode::BinaryFieldOp { + op: BinaryFieldOp::Equals, + lhs: MemoryAddress::direct(0), + rhs: MemoryAddress::direct(1), + destination: MemoryAddress::direct(4), + }; + let brillig_bytecode = BrilligBytecode { bytecode: vec![ BrilligOpcode::Const { - destination: MemoryAddress::direct(0), + destination: zero_usize, + bit_size: BitSize::Integer(IntegerBitSize::U32), + value: FieldElement::from(0u64), + }, + BrilligOpcode::Const { + destination: three_usize, bit_size: BitSize::Integer(IntegerBitSize::U32), value: FieldElement::from(3u64), }, BrilligOpcode::Const { - destination: MemoryAddress::direct(1), + destination: five_usize, bit_size: BitSize::Integer(IntegerBitSize::U32), - value: FieldElement::from(0u64), + value: FieldElement::from(5u64), }, BrilligOpcode::CalldataCopy { destination_address: MemoryAddress::direct(0), - size_address: MemoryAddress::direct(0), - offset_address: MemoryAddress::direct(1), + size_address: three_usize, + offset_address: zero_usize, }, equal_opcode, // Oracles are named 'foreign calls' in brillig @@ -301,7 +321,9 @@ fn double_inversion_brillig_oracle() { inputs: vec![ValueOrArray::MemoryAddress(MemoryAddress::direct(2))], input_value_types: vec![HeapValueType::field()], }, - BrilligOpcode::Stop { return_data_offset: 0, return_data_size: 5 }, + BrilligOpcode::Stop { + return_data: HeapVector { pointer: zero_usize, size: five_usize }, + }, ], }; @@ -386,22 +408,31 @@ fn oracle_dependent_execution() { let w_x_inv = Witness(3); let w_y_inv = Witness(4); + let zero_usize = MemoryAddress::direct(4); + let three_usize = MemoryAddress::direct(5); + let four_usize = MemoryAddress::direct(6); + let brillig_bytecode = BrilligBytecode { bytecode: vec![ BrilligOpcode::Const { - destination: MemoryAddress::direct(0), + destination: zero_usize, + bit_size: BitSize::Integer(IntegerBitSize::U32), + value: FieldElement::from(0u64), + }, + BrilligOpcode::Const { + destination: three_usize, bit_size: BitSize::Integer(IntegerBitSize::U32), value: FieldElement::from(3u64), }, BrilligOpcode::Const { - destination: MemoryAddress::direct(1), + destination: four_usize, bit_size: BitSize::Integer(IntegerBitSize::U32), - value: FieldElement::from(0u64), + value: FieldElement::from(4u64), }, BrilligOpcode::CalldataCopy { destination_address: MemoryAddress::direct(0), - size_address: MemoryAddress::direct(0), - offset_address: MemoryAddress::direct(1), + size_address: three_usize, + offset_address: zero_usize, }, // Oracles are named 'foreign calls' in brillig BrilligOpcode::ForeignCall { function: "invert".into(), @@ -417,7 +448,9 @@ fn oracle_dependent_execution() { inputs: vec![ValueOrArray::MemoryAddress(MemoryAddress::direct(2))], input_value_types: vec![HeapValueType::field()], }, - BrilligOpcode::Stop { return_data_offset: 0, return_data_size: 4 }, + BrilligOpcode::Stop { + return_data: HeapVector { pointer: zero_usize, size: four_usize }, + }, ], }; @@ -662,7 +695,7 @@ fn unsatisfied_opcode_resolved_brillig() { }; // Jump pass the trap if the values are equal, else // jump to the trap - let location_of_stop = 3; + let location_of_stop = 7; let jmp_if_opcode = BrilligOpcode::JumpIf { condition: MemoryAddress::direct(2), location: location_of_stop }; @@ -673,7 +706,12 @@ fn unsatisfied_opcode_resolved_brillig() { size: MemoryAddress::direct(3), }, }; - let stop_opcode = BrilligOpcode::Stop { return_data_offset: 0, return_data_size: 0 }; + let stop_opcode = BrilligOpcode::Stop { + return_data: HeapVector { + pointer: MemoryAddress::direct(0), + size: MemoryAddress::direct(3), + }, + }; let brillig_bytecode = BrilligBytecode { bytecode: vec![ diff --git a/noir/noir-repo/acvm-repo/acvm_js/test/shared/complex_foreign_call.ts b/noir/noir-repo/acvm-repo/acvm_js/test/shared/complex_foreign_call.ts index b2b0aff6ed3..755b5a7587b 100644 --- a/noir/noir-repo/acvm-repo/acvm_js/test/shared/complex_foreign_call.ts +++ b/noir/noir-repo/acvm-repo/acvm_js/test/shared/complex_foreign_call.ts @@ -2,14 +2,14 @@ import { WitnessMap } from '@noir-lang/acvm_js'; // See `complex_brillig_foreign_call` integration test in `acir/tests/test_program_serialization.rs`. export const bytecode = Uint8Array.from([ - 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 213, 85, 93, 10, 194, 48, 12, 78, 219, 233, 54, 240, 205, 11, 8, 122, 128, 76, 47, - 176, 187, 136, 111, 138, 62, 122, 124, 45, 75, 88, 140, 197, 9, 38, 224, 62, 24, 89, 75, 242, 229, 159, 6, 24, 208, - 60, 191, 64, 255, 11, 146, 145, 100, 190, 79, 240, 10, 214, 237, 73, 226, 111, 232, 130, 29, 23, 122, 197, 24, 103, - 16, 99, 114, 136, 17, 68, 255, 255, 176, 223, 150, 125, 49, 173, 95, 42, 236, 79, 5, 195, 126, 45, 233, 92, 147, 108, - 116, 161, 179, 81, 132, 247, 197, 147, 224, 225, 105, 149, 4, 229, 184, 183, 73, 232, 208, 42, 191, 198, 252, 200, - 197, 216, 192, 119, 249, 250, 228, 185, 71, 230, 79, 46, 252, 216, 49, 127, 229, 212, 167, 90, 213, 75, 230, 34, 253, - 174, 96, 28, 192, 227, 245, 114, 59, 159, 238, 169, 96, 170, 205, 51, 182, 234, 188, 43, 148, 108, 138, 131, 33, 223, - 153, 79, 250, 161, 160, 63, 101, 179, 134, 113, 156, 248, 93, 123, 0, 142, 67, 44, 107, 244, 6, 0, 0, + 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 213, 85, 205, 14, 130, 48, 12, 238, 54, 20, 136, 222, 124, 1, 19, 125, 128, 161, + 241, 238, 187, 24, 111, 26, 61, 250, 248, 186, 208, 198, 89, 26, 56, 216, 18, 248, 18, 82, 6, 237, 215, 255, 204, 65, + 139, 234, 243, 56, 124, 95, 160, 244, 40, 211, 247, 0, 191, 32, 221, 51, 202, 248, 31, 26, 167, 199, 21, 173, 98, 244, + 51, 136, 49, 24, 196, 8, 89, 255, 39, 216, 111, 205, 190, 168, 214, 47, 8, 251, 83, 64, 187, 95, 75, 60, 151, 40, 43, + 94, 232, 100, 228, 161, 187, 120, 57, 104, 120, 86, 40, 107, 225, 191, 98, 66, 199, 154, 249, 85, 230, 143, 84, 140, + 45, 244, 231, 107, 155, 231, 33, 18, 127, 48, 225, 143, 13, 241, 23, 70, 125, 42, 89, 189, 242, 92, 114, 191, 107, + 248, 14, 224, 229, 113, 127, 222, 174, 175, 32, 152, 114, 243, 132, 29, 59, 239, 133, 146, 13, 113, 16, 242, 123, 166, + 79, 223, 9, 250, 67, 54, 99, 141, 138, 209, 74, 156, 54, 208, 5, 249, 122, 3, 73, 2, 62, 54, 188, 7, 0, 0, ]); export const initialWitnessMap: WitnessMap = new Map([ [1, '0x0000000000000000000000000000000000000000000000000000000000000001'], diff --git a/noir/noir-repo/acvm-repo/acvm_js/test/shared/foreign_call.ts b/noir/noir-repo/acvm-repo/acvm_js/test/shared/foreign_call.ts index 6cec99a636d..37b70e23a3a 100644 --- a/noir/noir-repo/acvm-repo/acvm_js/test/shared/foreign_call.ts +++ b/noir/noir-repo/acvm-repo/acvm_js/test/shared/foreign_call.ts @@ -2,11 +2,11 @@ import { WitnessMap } from '@noir-lang/acvm_js'; // See `simple_brillig_foreign_call` integration test in `acir/tests/test_program_serialization.rs`. export const bytecode = Uint8Array.from([ - 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 173, 79, 73, 10, 128, 48, 12, 236, 40, 46, 5, 111, 126, 36, 254, 192, 207, 120, - 240, 226, 65, 196, 247, 91, 48, 129, 80, 186, 28, 154, 129, 144, 201, 132, 44, 3, 247, 99, 14, 1, 230, 3, 103, 169, - 53, 68, 219, 57, 83, 27, 54, 216, 237, 34, 253, 111, 23, 19, 104, 177, 96, 76, 204, 251, 68, 191, 55, 52, 238, 163, - 187, 198, 251, 105, 114, 101, 200, 221, 37, 196, 200, 252, 188, 222, 227, 126, 80, 153, 200, 213, 57, 125, 77, 244, - 62, 112, 171, 6, 33, 119, 2, 0, 0, + 31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 173, 81, 203, 10, 128, 48, 12, 179, 19, 31, 3, 111, 254, 200, 246, 7, 254, 140, 7, + 47, 30, 68, 252, 126, 39, 182, 80, 70, 182, 203, 26, 40, 73, 3, 43, 9, 163, 238, 199, 156, 134, 88, 15, 204, 178, 107, + 136, 183, 49, 135, 54, 68, 178, 187, 21, 116, 94, 151, 11, 210, 102, 165, 152, 148, 247, 153, 255, 113, 111, 24, 214, + 131, 124, 134, 247, 227, 4, 58, 58, 208, 119, 73, 51, 178, 62, 206, 103, 191, 110, 244, 237, 250, 69, 105, 47, 249, + 43, 240, 37, 201, 11, 205, 95, 230, 87, 127, 2, 0, 0, ]); export const initialWitnessMap: WitnessMap = new Map([ [1, '0x0000000000000000000000000000000000000000000000000000000000000005'], diff --git a/noir/noir-repo/acvm-repo/brillig/src/opcodes.rs b/noir/noir-repo/acvm-repo/brillig/src/opcodes.rs index 0d87c5b9410..8b72b5a9b41 100644 --- a/noir/noir-repo/acvm-repo/brillig/src/opcodes.rs +++ b/noir/noir-repo/acvm-repo/brillig/src/opcodes.rs @@ -309,8 +309,7 @@ pub enum BrilligOpcode { }, /// Stop execution, returning data after the offset Stop { - return_data_offset: usize, - return_data_size: usize, + return_data: HeapVector, }, } diff --git a/noir/noir-repo/acvm-repo/brillig_vm/src/lib.rs b/noir/noir-repo/acvm-repo/brillig_vm/src/lib.rs index 89d72c4614b..0a1614a98fc 100644 --- a/noir/noir-repo/acvm-repo/brillig_vm/src/lib.rs +++ b/noir/noir-repo/acvm-repo/brillig_vm/src/lib.rs @@ -357,8 +357,16 @@ impl<'a, F: AcirField, B: BlackBoxFunctionSolver> VM<'a, F, B> { self.trap(0, 0) } } - Opcode::Stop { return_data_offset, return_data_size } => { - self.finish(*return_data_offset, *return_data_size) + Opcode::Stop { return_data } => { + let return_data_size = self.memory.read(return_data.size).to_usize(); + if return_data_size > 0 { + self.finish( + self.memory.read_ref(return_data.pointer).unwrap_direct(), + return_data_size, + ) + } else { + self.finish(0, 0) + } } Opcode::Load { destination: destination_address, source_pointer } => { // Convert our source_pointer to an address @@ -1005,28 +1013,37 @@ mod tests { fn cast_opcode() { let calldata: Vec = vec![((2_u128.pow(32)) - 1).into()]; + let value_address = MemoryAddress::direct(1); + let one_usize = MemoryAddress::direct(2); + let zero_usize = MemoryAddress::direct(3); + let opcodes = &[ Opcode::Const { - destination: MemoryAddress::direct(0), + destination: one_usize, bit_size: BitSize::Integer(IntegerBitSize::U32), value: FieldElement::from(1u64), }, Opcode::Const { - destination: MemoryAddress::direct(1), + destination: zero_usize, bit_size: BitSize::Integer(IntegerBitSize::U32), value: FieldElement::from(0u64), }, Opcode::CalldataCopy { - destination_address: MemoryAddress::direct(0), - size_address: MemoryAddress::direct(0), - offset_address: MemoryAddress::direct(1), + destination_address: value_address, + size_address: one_usize, + offset_address: zero_usize, }, Opcode::Cast { - destination: MemoryAddress::direct(1), - source: MemoryAddress::direct(0), + destination: value_address, + source: value_address, bit_size: BitSize::Integer(IntegerBitSize::U8), }, - Opcode::Stop { return_data_offset: 1, return_data_size: 1 }, + Opcode::Stop { + return_data: HeapVector { + pointer: one_usize, // Since value_address is direct(1) + size: one_usize, + }, + }, ]; let mut vm = VM::new(calldata, opcodes, vec![], &StubbedBlackBoxSolver, false); @@ -1051,33 +1068,42 @@ mod tests { fn not_opcode() { let calldata: Vec = vec![(1_usize).into()]; + let value_address = MemoryAddress::direct(1); + let one_usize = MemoryAddress::direct(2); + let zero_usize = MemoryAddress::direct(3); + let opcodes = &[ Opcode::Const { - destination: MemoryAddress::direct(0), + destination: one_usize, bit_size: BitSize::Integer(IntegerBitSize::U32), value: FieldElement::from(1u64), }, Opcode::Const { - destination: MemoryAddress::direct(1), + destination: zero_usize, bit_size: BitSize::Integer(IntegerBitSize::U32), value: FieldElement::from(0u64), }, Opcode::CalldataCopy { - destination_address: MemoryAddress::direct(0), - size_address: MemoryAddress::direct(0), - offset_address: MemoryAddress::direct(1), + destination_address: value_address, + size_address: one_usize, + offset_address: zero_usize, }, Opcode::Cast { - destination: MemoryAddress::direct(1), - source: MemoryAddress::direct(0), + destination: value_address, + source: value_address, bit_size: BitSize::Integer(IntegerBitSize::U128), }, Opcode::Not { - destination: MemoryAddress::direct(1), - source: MemoryAddress::direct(1), + destination: value_address, + source: value_address, bit_size: IntegerBitSize::U128, }, - Opcode::Stop { return_data_offset: 1, return_data_size: 1 }, + Opcode::Stop { + return_data: HeapVector { + pointer: one_usize, // Since value_address is direct(1) + size: one_usize, + }, + }, ]; let mut vm = VM::new(calldata, opcodes, vec![], &StubbedBlackBoxSolver, false); diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_directive.rs b/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_directive.rs index 854014eb1d2..fc2746a7b53 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_directive.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_directive.rs @@ -1,5 +1,7 @@ use acvm::acir::{ - brillig::{BinaryFieldOp, BitSize, IntegerBitSize, MemoryAddress, Opcode as BrilligOpcode}, + brillig::{ + BinaryFieldOp, BitSize, HeapVector, IntegerBitSize, MemoryAddress, Opcode as BrilligOpcode, + }, AcirField, }; @@ -18,25 +20,27 @@ pub(crate) fn directive_invert() -> GeneratedBrillig { let one_const = MemoryAddress::direct(1); let zero_const = MemoryAddress::direct(2); let input_is_zero = MemoryAddress::direct(3); + let zero_usize = MemoryAddress::direct(20); + let one_usize = MemoryAddress::direct(21); // Location of the stop opcode let stop_location = 8; GeneratedBrillig { byte_code: vec![ BrilligOpcode::Const { - destination: MemoryAddress::direct(20), + destination: one_usize, bit_size: BitSize::Integer(IntegerBitSize::U32), value: F::from(1_usize), }, BrilligOpcode::Const { - destination: MemoryAddress::direct(21), + destination: zero_usize, bit_size: BitSize::Integer(IntegerBitSize::U32), value: F::from(0_usize), }, BrilligOpcode::CalldataCopy { destination_address: input, - size_address: MemoryAddress::direct(20), - offset_address: MemoryAddress::direct(21), + size_address: one_usize, + offset_address: zero_usize, }, // Put value zero in register (2) BrilligOpcode::Const { @@ -65,7 +69,9 @@ pub(crate) fn directive_invert() -> GeneratedBrillig { rhs: input, destination: input, }, - BrilligOpcode::Stop { return_data_offset: 0, return_data_size: 1 }, + BrilligOpcode::Stop { + return_data: HeapVector { pointer: zero_usize, size: one_usize }, + }, ], error_types: Default::default(), locations: Default::default(), @@ -131,7 +137,12 @@ pub(crate) fn directive_quotient() -> GeneratedBrillig { destination: MemoryAddress::direct(0), source: MemoryAddress::direct(2), }, - BrilligOpcode::Stop { return_data_offset: 0, return_data_size: 2 }, + BrilligOpcode::Stop { + return_data: HeapVector { + pointer: MemoryAddress::direct(11), + size: MemoryAddress::direct(10), + }, + }, ], error_types: Default::default(), locations: Default::default(), diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir.rs b/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir.rs index 3633700a795..c062ede3316 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir.rs @@ -296,12 +296,12 @@ pub(crate) mod tests { // We push a JumpIf and Trap opcode directly as the constrain instruction // uses unresolved jumps which requires a block to be constructed in SSA and // we don't need this for Brillig IR tests - context.push_opcode(BrilligOpcode::JumpIf { condition: r_equality, location: 9 }); context.push_opcode(BrilligOpcode::Const { destination: MemoryAddress::direct(0), bit_size: BitSize::Integer(IntegerBitSize::U32), value: FieldElement::from(0u64), }); + context.push_opcode(BrilligOpcode::JumpIf { condition: r_equality, location: 9 }); context.push_opcode(BrilligOpcode::Trap { revert_data: HeapVector { pointer: MemoryAddress::direct(0), @@ -309,7 +309,10 @@ pub(crate) mod tests { }, }); - context.stop_instruction(); + context.stop_instruction(HeapVector { + pointer: MemoryAddress::direct(0), + size: MemoryAddress::direct(0), + }); let bytecode: Vec> = context.artifact().finish().byte_code; let number_sequence: Vec = diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/artifact.rs b/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/artifact.rs index 40a133d5e38..0e5b72c0b85 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/artifact.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/artifact.rs @@ -180,17 +180,7 @@ impl BrilligArtifact { self.error_types.insert(*error_selector, error_type.clone()); } - let mut byte_code = obj.byte_code.clone(); - - // Replace STOP with RETURN because this is not the end of the program now. - let stop_position = byte_code - .iter() - .position(|opcode| matches!(opcode, BrilligOpcode::Stop { .. })) - .expect("Trying to link with a function that does not have a stop opcode"); - - byte_code[stop_position] = BrilligOpcode::Return; - - self.byte_code.append(&mut byte_code); + self.byte_code.append(&mut obj.byte_code.clone()); // Remove all resolved external calls and transform them to jumps let is_resolved = |label: &Label| self.labels.contains_key(label); diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/codegen_calls.rs b/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/codegen_calls.rs index 777acfc4da3..da310873cff 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/codegen_calls.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/codegen_calls.rs @@ -73,6 +73,6 @@ impl BrilligContext { .iter() .for_each(|destination| self.registers.ensure_register_is_allocated(*destination)); self.codegen_mov_registers_to_registers(sources, destinations); - self.stop_instruction(); + self.return_instruction(); } } diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/debug_show.rs b/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/debug_show.rs index 4e82a0d3af5..55a24264fbb 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/debug_show.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/debug_show.rs @@ -211,23 +211,14 @@ impl DebugShow { debug_println!(self.enable_debug_trace, " STORE *{} = {}", destination_pointer, source); } - /// Emits a stop instruction - pub(crate) fn stop_instruction(&self) { - debug_println!(self.enable_debug_trace, " STOP"); + /// Emits a return instruction + pub(crate) fn return_instruction(&self) { + debug_println!(self.enable_debug_trace, " RETURN"); } - /// Emits a external stop instruction (returns data) - pub(crate) fn external_stop_instruction( - &self, - return_data_offset: usize, - return_data_size: usize, - ) { - debug_println!( - self.enable_debug_trace, - " EXT_STOP {}..{}", - return_data_offset, - return_data_offset + return_data_size - ); + /// Emits a stop instruction + pub(crate) fn stop_instruction(&self, return_data: HeapVector) { + debug_println!(self.enable_debug_trace, " STOP {}", return_data); } /// Debug function for enter_context diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/entry_point.rs b/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/entry_point.rs index b78dcb09d9a..2dbee48b277 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/entry_point.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/entry_point.rs @@ -7,7 +7,10 @@ use super::{ registers::Stack, BrilligBinaryOp, BrilligContext, ReservedRegisters, }; -use acvm::acir::{brillig::MemoryAddress, AcirField}; +use acvm::acir::{ + brillig::{HeapVector, MemoryAddress}, + AcirField, +}; pub(crate) const MAX_STACK_SIZE: usize = 16 * MAX_STACK_FRAME_SIZE; pub(crate) const MAX_STACK_FRAME_SIZE: usize = 2048; @@ -363,7 +366,12 @@ impl BrilligContext { } } - self.external_stop_instruction(return_data_offset, return_data_size); + let return_data = HeapVector { + pointer: self.make_usize_constant_instruction(return_data_offset.into()).address, + size: self.make_usize_constant_instruction(return_data_size.into()).address, + }; + + self.stop_instruction(return_data); } } diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/instructions.rs b/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/instructions.rs index 873b47b8694..2bf5364414c 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/instructions.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/instructions.rs @@ -257,20 +257,16 @@ impl BrilligContext< self.compute_section_label(self.current_section) } - /// Emits a stop instruction - pub(crate) fn stop_instruction(&mut self) { - self.debug_show.stop_instruction(); - self.push_opcode(BrilligOpcode::Stop { return_data_offset: 0, return_data_size: 0 }); + /// Emits a return instruction + pub(crate) fn return_instruction(&mut self) { + self.debug_show.return_instruction(); + self.push_opcode(BrilligOpcode::Return); } - /// Emits a external stop instruction (returns data) - pub(crate) fn external_stop_instruction( - &mut self, - return_data_offset: usize, - return_data_size: usize, - ) { - self.debug_show.external_stop_instruction(return_data_offset, return_data_size); - self.push_opcode(BrilligOpcode::Stop { return_data_offset, return_data_size }); + /// Emits a stop instruction with return data + pub(crate) fn stop_instruction(&mut self, return_data: HeapVector) { + self.debug_show.stop_instruction(return_data); + self.push_opcode(BrilligOpcode::Stop { return_data }); } /// Issues a blackbox operation. diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/procedures/mod.rs b/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/procedures/mod.rs index cbcf0543efb..1678268d343 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/procedures/mod.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_ir/procedures/mod.rs @@ -138,7 +138,7 @@ pub(crate) fn compile_procedure( } }; - brillig_context.stop_instruction(); + brillig_context.return_instruction(); brillig_context.artifact() } diff --git a/noir/noir-repo/tooling/debugger/src/context.rs b/noir/noir-repo/tooling/debugger/src/context.rs index 3f64fc1acdb..bec30976552 100644 --- a/noir/noir-repo/tooling/debugger/src/context.rs +++ b/noir/noir-repo/tooling/debugger/src/context.rs @@ -954,7 +954,7 @@ mod tests { use crate::foreign_calls::DefaultDebugForeignCallExecutor; use acvm::{ acir::{ - brillig::IntegerBitSize, + brillig::{HeapVector, IntegerBitSize}, circuit::{ brillig::{BrilligFunctionId, BrilligInputs, BrilligOutputs}, opcodes::{AcirFunctionId, BlockId, BlockType}, @@ -970,31 +970,25 @@ mod tests { #[test] fn test_resolve_foreign_calls_stepping_into_brillig() { - let fe_0 = FieldElement::zero(); let fe_1 = FieldElement::one(); let w_x = Witness(1); let brillig_bytecode = BrilligBytecode { bytecode: vec![ BrilligOpcode::Const { - destination: MemoryAddress::direct(0), + destination: MemoryAddress::direct(1), bit_size: BitSize::Integer(IntegerBitSize::U32), value: FieldElement::from(1u64), }, BrilligOpcode::Const { - destination: MemoryAddress::direct(1), + destination: MemoryAddress::direct(2), bit_size: BitSize::Integer(IntegerBitSize::U32), value: FieldElement::from(0u64), }, BrilligOpcode::CalldataCopy { destination_address: MemoryAddress::direct(0), - size_address: MemoryAddress::direct(0), - offset_address: MemoryAddress::direct(1), - }, - BrilligOpcode::Const { - destination: MemoryAddress::direct(1), - value: fe_0, - bit_size: BitSize::Integer(IntegerBitSize::U32), + size_address: MemoryAddress::direct(1), + offset_address: MemoryAddress::direct(2), }, BrilligOpcode::ForeignCall { function: "clear_mock".into(), @@ -1003,7 +997,12 @@ mod tests { inputs: vec![ValueOrArray::MemoryAddress(MemoryAddress::direct(0))], input_value_types: vec![HeapValueType::field()], }, - BrilligOpcode::Stop { return_data_offset: 0, return_data_size: 0 }, + BrilligOpcode::Stop { + return_data: HeapVector { + pointer: MemoryAddress::direct(2), + size: MemoryAddress::direct(2), + }, + }, ], }; let opcodes = vec![Opcode::BrilligCall { @@ -1082,18 +1081,6 @@ mod tests { }) ); - // Const - let result = context.step_into_opcode(); - assert!(matches!(result, DebugCommandResult::Ok)); - assert_eq!( - context.get_current_debug_location(), - Some(DebugLocation { - circuit_id: 0, - opcode_location: OpcodeLocation::Brillig { acir_index: 0, brillig_index: 4 }, - brillig_function_id: Some(BrilligFunctionId(0)), - }) - ); - // try to execute the Brillig opcode (and resolve the foreign call) let result = context.step_into_opcode(); assert!(matches!(result, DebugCommandResult::Ok)); @@ -1101,7 +1088,7 @@ mod tests { context.get_current_debug_location(), Some(DebugLocation { circuit_id: 0, - opcode_location: OpcodeLocation::Brillig { acir_index: 0, brillig_index: 4 }, + opcode_location: OpcodeLocation::Brillig { acir_index: 0, brillig_index: 3 }, brillig_function_id: Some(BrilligFunctionId(0)), }) ); @@ -1113,7 +1100,7 @@ mod tests { context.get_current_debug_location(), Some(DebugLocation { circuit_id: 0, - opcode_location: OpcodeLocation::Brillig { acir_index: 0, brillig_index: 5 }, + opcode_location: OpcodeLocation::Brillig { acir_index: 0, brillig_index: 4 }, brillig_function_id: Some(BrilligFunctionId(0)), }) ); @@ -1132,6 +1119,9 @@ mod tests { let w_y = Witness(2); let w_z = Witness(3); + let zero_usize = MemoryAddress::direct(2); + let one_usize = MemoryAddress::direct(3); + // This Brillig block is equivalent to: z = x + y let brillig_bytecode = BrilligBytecode { bytecode: vec![ @@ -1141,14 +1131,19 @@ mod tests { value: FieldElement::from(2u64), }, BrilligOpcode::Const { - destination: MemoryAddress::direct(1), + destination: zero_usize, bit_size: BitSize::Integer(IntegerBitSize::U32), value: FieldElement::from(0u64), }, + BrilligOpcode::Const { + destination: one_usize, + bit_size: BitSize::Integer(IntegerBitSize::U32), + value: FieldElement::from(1u64), + }, BrilligOpcode::CalldataCopy { destination_address: MemoryAddress::direct(0), size_address: MemoryAddress::direct(0), - offset_address: MemoryAddress::direct(1), + offset_address: zero_usize, }, BrilligOpcode::BinaryFieldOp { destination: MemoryAddress::direct(0), @@ -1156,7 +1151,9 @@ mod tests { lhs: MemoryAddress::direct(0), rhs: MemoryAddress::direct(1), }, - BrilligOpcode::Stop { return_data_offset: 0, return_data_size: 1 }, + BrilligOpcode::Stop { + return_data: HeapVector { pointer: zero_usize, size: one_usize }, + }, ], }; let opcodes = vec![ @@ -1238,18 +1235,10 @@ mod tests { #[test] fn test_address_debug_location_mapping() { - let brillig_one = BrilligBytecode { - bytecode: vec![ - BrilligOpcode::Stop { return_data_offset: 0, return_data_size: 0 }, - BrilligOpcode::Stop { return_data_offset: 0, return_data_size: 0 }, - ], - }; + let brillig_one = + BrilligBytecode { bytecode: vec![BrilligOpcode::Return, BrilligOpcode::Return] }; let brillig_two = BrilligBytecode { - bytecode: vec![ - BrilligOpcode::Stop { return_data_offset: 0, return_data_size: 0 }, - BrilligOpcode::Stop { return_data_offset: 0, return_data_size: 0 }, - BrilligOpcode::Stop { return_data_offset: 0, return_data_size: 0 }, - ], + bytecode: vec![BrilligOpcode::Return, BrilligOpcode::Return, BrilligOpcode::Return], }; let circuit_one = Circuit { diff --git a/yarn-project/simulator/src/avm/avm_simulator.test.ts b/yarn-project/simulator/src/avm/avm_simulator.test.ts index eb744ab15cb..e8a44d0df61 100644 --- a/yarn-project/simulator/src/avm/avm_simulator.test.ts +++ b/yarn-project/simulator/src/avm/avm_simulator.test.ts @@ -82,7 +82,8 @@ describe('AVM simulator: injected bytecode', () => { new Set(/*indirect*/ 0, TypeTag.UINT32, /*value*/ 2, /*dstOffset*/ 1).as(Opcode.SET_8, Set.wireFormat8), new CalldataCopy(/*indirect=*/ 0, /*cdOffset=*/ 0, /*copySize=*/ 1, /*dstOffset=*/ 0), new Add(/*indirect=*/ 0, /*aOffset=*/ 0, /*bOffset=*/ 1, /*dstOffset=*/ 2).as(Opcode.ADD_8, Add.wireFormat8), - new Return(/*indirect=*/ 0, /*returnOffset=*/ 2, /*copySize=*/ 1), + new Set(/*indirect*/ 0, TypeTag.UINT32, /*value*/ 1, /*dstOffset*/ 0).as(Opcode.SET_8, Set.wireFormat8), + new Return(/*indirect=*/ 0, /*returnOffset=*/ 2, /*copySizeOffset=*/ 0), ]); }); diff --git a/yarn-project/simulator/src/avm/opcodes/external_calls.test.ts b/yarn-project/simulator/src/avm/opcodes/external_calls.test.ts index 4bc38e78d2c..534a45102b7 100644 --- a/yarn-project/simulator/src/avm/opcodes/external_calls.test.ts +++ b/yarn-project/simulator/src/avm/opcodes/external_calls.test.ts @@ -74,8 +74,9 @@ describe('External Calls', () => { encodeToBytecode([ new Set(/*indirect=*/ 0, TypeTag.UINT32, 0, /*dstOffset=*/ 0).as(Opcode.SET_8, Set.wireFormat8), new Set(/*indirect=*/ 0, TypeTag.UINT32, argsSize, /*dstOffset=*/ 1).as(Opcode.SET_8, Set.wireFormat8), - new CalldataCopy(/*indirect=*/ 0, /*csOffsetAddress=*/ 0, /*copySizeOffset=*/ 1, /*dstOffset=*/ 0), - new Return(/*indirect=*/ 0, /*retOffset=*/ 0, /*size=*/ 2), + new Set(/*indirect=*/ 0, TypeTag.UINT32, 2, /*dstOffset=*/ 2).as(Opcode.SET_8, Set.wireFormat8), + new CalldataCopy(/*indirect=*/ 0, /*csOffsetAddress=*/ 0, /*copySizeOffset=*/ 1, /*dstOffset=*/ 3), + new Return(/*indirect=*/ 0, /*retOffset=*/ 3, /*sizeOffset=*/ 2), ]), ); mockGetBytecode(worldStateDB, otherContextInstructionsBytecode); @@ -125,6 +126,7 @@ describe('External Calls', () => { Opcode.GETENVVAR_16, GetEnvVar.wireFormat16, ), + new Set(/*indirect=*/ 0, TypeTag.UINT32, 1, /*dstOffset=*/ 1).as(Opcode.SET_8, Set.wireFormat8), new Return(/*indirect=*/ 0, /*retOffset=*/ 0, /*size=*/ 1), ]), ); @@ -259,8 +261,9 @@ describe('External Calls', () => { context.machineState.memory.set(0, new Field(1n)); context.machineState.memory.set(1, new Field(2n)); context.machineState.memory.set(2, new Field(3n)); + context.machineState.memory.set(3, new Uint32(returnData.length)); - const instruction = new Return(/*indirect=*/ 0, /*returnOffset=*/ 0, returnData.length); + const instruction = new Return(/*indirect=*/ 0, /*returnOffset=*/ 0, 3); await instruction.execute(context); expect(context.machineState.getHalted()).toBe(true); diff --git a/yarn-project/simulator/src/avm/opcodes/external_calls.ts b/yarn-project/simulator/src/avm/opcodes/external_calls.ts index 64c5fc64252..9b52a8ff160 100644 --- a/yarn-project/simulator/src/avm/opcodes/external_calls.ts +++ b/yarn-project/simulator/src/avm/opcodes/external_calls.ts @@ -142,22 +142,25 @@ export class Return extends Instruction { OperandType.UINT16, ]; - constructor(private indirect: number, private returnOffset: number, private copySize: number) { + constructor(private indirect: number, private returnOffset: number, private returnSizeOffset: number) { super(); } public async execute(context: AvmContext): Promise { const memory = context.machineState.memory.track(this.type); - context.machineState.consumeGas(this.gasCost(this.copySize)); - const operands = [this.returnOffset]; + const operands = [this.returnOffset, this.returnSizeOffset]; const addressing = Addressing.fromWire(this.indirect, operands.length); - const [returnOffset] = addressing.resolve(operands, memory); + const [returnOffset, returnSizeOffset] = addressing.resolve(operands, memory); - const output = memory.getSlice(returnOffset, this.copySize).map(word => word.toFr()); + memory.checkTag(TypeTag.UINT32, returnSizeOffset); + const returnSize = memory.get(returnSizeOffset).toNumber(); + context.machineState.consumeGas(this.gasCost(returnSize)); + + const output = memory.getSlice(returnOffset, returnSize).map(word => word.toFr()); context.machineState.return(output); - memory.assert({ reads: this.copySize, addressing }); + memory.assert({ reads: returnSize + 1, addressing }); } public override handlesPC(): boolean {