Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Stop with HeapVector #9810

Merged
merged 12 commits into from
Nov 12, 2024
59 changes: 34 additions & 25 deletions avm-transpiler/src/transpile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -306,16 +306,12 @@ pub fn brillig_to_avm(brillig_bytecode: &[BrilligOpcode<FieldElement>]) -> (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(
Expand Down Expand Up @@ -960,6 +956,28 @@ fn generate_revert_instruction(
});
}

/// Generates an AVM RETURN instruction.
fn generate_return_instruction(
avm_instrs: &mut Vec<AvmInstruction>,
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<AvmOperand>,
Expand Down Expand Up @@ -1323,25 +1341,16 @@ fn handle_return(
destinations: &Vec<ValueOrArray>,
inputs: &Vec<ValueOrArray>,
) {
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)]
Expand Down
14 changes: 4 additions & 10 deletions barretenberg/cpp/src/barretenberg/dsl/acir_format/serde/acir.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<uint8_t> bincodeSerialize() const;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -6434,8 +6430,7 @@ template <typename Serializer>
void serde::Serializable<Program::BrilligOpcode::Stop>::serialize(const Program::BrilligOpcode::Stop& obj,
Serializer& serializer)
{
serde::Serializable<decltype(obj.return_data_offset)>::serialize(obj.return_data_offset, serializer);
serde::Serializable<decltype(obj.return_data_size)>::serialize(obj.return_data_size, serializer);
serde::Serializable<decltype(obj.return_data)>::serialize(obj.return_data, serializer);
}

template <>
Expand All @@ -6444,8 +6439,7 @@ Program::BrilligOpcode::Stop serde::Deserializable<Program::BrilligOpcode::Stop>
Deserializer& deserializer)
{
Program::BrilligOpcode::Stop obj;
obj.return_data_offset = serde::Deserializable<decltype(obj.return_data_offset)>::deserialize(deserializer);
obj.return_data_size = serde::Deserializable<decltype(obj.return_data_size)>::deserialize(deserializer);
obj.return_data = serde::Deserializable<decltype(obj.return_data)>::deserialize(deserializer);
return obj;
}

Expand Down
16 changes: 10 additions & 6 deletions barretenberg/cpp/src/barretenberg/vm/avm/trace/trace.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2884,9 +2884,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<FF> AvmTraceBuilder::op_return(uint8_t indirect, uint32_t ret_offset, uint32_t ret_size)
std::vector<FF> AvmTraceBuilder::op_return(uint8_t indirect, uint32_t ret_offset, uint32_t ret_size_offset)
{
auto clk = static_cast<uint32_t>(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<uint32_t>(unconstrained_read_from_memory(resolved_ret_size_offset));

gas_trace_builder.constrain_gas(clk, OpCode::RETURN, ret_size);

if (ret_size == 0) {
Expand All @@ -2903,11 +2912,6 @@ std::vector<FF> 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.
Expand Down
4 changes: 2 additions & 2 deletions noir-projects/aztec-nr/aztec/src/context/public_context.nr
Original file line number Diff line number Diff line change
Expand Up @@ -287,7 +287,7 @@ unconstrained fn returndata_copy(rdoffset: u32, copy_size: u32) -> [Field] {
returndata_copy_opcode(rdoffset, copy_size)
}

unconstrained fn avm_return<let N: u32>(returndata: [Field; N]) {
unconstrained fn avm_return(returndata: [Field]) {
return_opcode(returndata)
}

Expand Down Expand Up @@ -388,7 +388,7 @@ unconstrained fn returndata_size_opcode() -> u32 {}
unconstrained fn returndata_copy_opcode(rdoffset: u32, copy_size: u32) -> [Field] {}

#[oracle(avmOpcodeReturn)]
unconstrained fn return_opcode<let N: u32>(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.
Expand Down
2 changes: 1 addition & 1 deletion noir-projects/aztec-nr/aztec/src/macros/dispatch/mod.nr
Original file line number Diff line number Diff line change
Expand Up @@ -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());
}
};

Expand Down
12 changes: 4 additions & 8 deletions noir/noir-repo/acvm-repo/acir/codegen/acir.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<uint8_t> bincodeSerialize() const;
Expand Down Expand Up @@ -5333,8 +5332,7 @@ Program::BrilligOpcode::Trap serde::Deserializable<Program::BrilligOpcode::Trap>
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;
}

Expand All @@ -5358,16 +5356,14 @@ namespace Program {
template <>
template <typename Serializer>
void serde::Serializable<Program::BrilligOpcode::Stop>::serialize(const Program::BrilligOpcode::Stop &obj, Serializer &serializer) {
serde::Serializable<decltype(obj.return_data_offset)>::serialize(obj.return_data_offset, serializer);
serde::Serializable<decltype(obj.return_data_size)>::serialize(obj.return_data_size, serializer);
serde::Serializable<decltype(obj.return_data)>::serialize(obj.return_data, serializer);
}

template <>
template <typename Deserializer>
Program::BrilligOpcode::Stop serde::Deserializable<Program::BrilligOpcode::Stop>::deserialize(Deserializer &deserializer) {
Program::BrilligOpcode::Stop obj;
obj.return_data_offset = serde::Deserializable<decltype(obj.return_data_offset)>::deserialize(deserializer);
obj.return_data_size = serde::Deserializable<decltype(obj.return_data_size)>::deserialize(deserializer);
obj.return_data = serde::Deserializable<decltype(obj.return_data)>::deserialize(deserializer);
return obj;
}

Expand Down
81 changes: 52 additions & 29 deletions noir/noir-repo/acvm-repo/acir/tests/test_program_serialization.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand Down Expand Up @@ -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 },
},
],
};

Expand Down Expand Up @@ -214,12 +222,12 @@ fn simple_brillig_foreign_call() {
let bytes = Program::serialize_program(&program);

let expected_serialization: Vec<u8> = 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)
Expand Down Expand Up @@ -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),
},
},
],
};

Expand Down Expand Up @@ -344,17 +367,17 @@ fn complex_brillig_foreign_call() {

let bytes = Program::serialize_program(&program);
let expected_serialization: Vec<u8> = 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)
Expand Down
Loading
Loading