diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.cpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.cpp index 091dd13752f..8fb66b1b522 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.cpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_format.cpp @@ -190,7 +190,6 @@ void build_constraints(Builder& builder, } // Add block constraints - assign_calldata_ids(constraint_system.block_constraints); for (size_t i = 0; i < constraint_system.block_constraints.size(); ++i) { const auto& constraint = constraint_system.block_constraints.at(i); create_block_constraints(builder, constraint, has_valid_witness_assignments); diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_to_constraint_buf.cpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_to_constraint_buf.cpp index d50bcd90495..7170c7a187d 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_to_constraint_buf.cpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_to_constraint_buf.cpp @@ -518,6 +518,7 @@ BlockConstraint handle_memory_init(Program::Opcode::MemoryInit const& mem_init) // array. if (std::holds_alternative(mem_init.block_type.value)) { block.type = BlockType::CallData; + block.calldata_id = std::get(mem_init.block_type.value).value; } else if (std::holds_alternative(mem_init.block_type.value)) { block.type = BlockType::ReturnData; } diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/block_constraint.cpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/block_constraint.cpp index f31501bdfda..4a81d284b5f 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/block_constraint.cpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/block_constraint.cpp @@ -213,20 +213,4 @@ void process_return_data_operations(const BlockConstraint& constraint, std::vect ASSERT(constraint.trace.size() == 0); } -// Do nothing for Ultra since it does not support Databus -template <> void assign_calldata_ids([[maybe_unused]] std::vector& constraints) {} - -template <> void assign_calldata_ids(std::vector& constraints) -{ - // Assign unique ID to each calldata block constraint - uint32_t calldata_id = 0; - for (auto& constraint : constraints) { - if (constraint.type == BlockType::CallData) { - constraint.calldata_id = calldata_id++; - } - } - // The backend only supports 2 calldata columns - ASSERT(calldata_id <= 2); -} - } // namespace acir_format \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/block_constraint.hpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/block_constraint.hpp index 4fccf1d9998..a165841dbdd 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/block_constraint.hpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/block_constraint.hpp @@ -48,16 +48,6 @@ void process_call_data_operations(Builder& builder, template void process_return_data_operations(const BlockConstraint& constraint, std::vector>& init); -/** - * @brief Assign a unique ID to each calldata block constraint based on the order in which it was recieved - * TODO(https://github.com/AztecProtocol/barretenberg/issues/1070): this is a workaround to allow calldata inputs to be - * distinguished by the backend since no identifiers are received from noir. - * - * @tparam Builder - * @param constraints - */ -template void assign_calldata_ids(std::vector& constraints); - template inline void read(B& buf, MemOp& mem_op) { using serialize::read; 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 74b9bb60de9..0a4d49c56fe 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/serde/acir.hpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/serde/acir.hpp @@ -1107,6 +1107,8 @@ struct BlockType { }; struct CallData { + uint32_t value; + friend bool operator==(const CallData&, const CallData&); std::vector bincodeSerialize() const; static CallData bincodeDeserialize(std::vector); @@ -5578,6 +5580,9 @@ namespace Program { inline bool operator==(const BlockType::CallData& lhs, const BlockType::CallData& rhs) { + if (!(lhs.value == rhs.value)) { + return false; + } return true; } @@ -5604,7 +5609,9 @@ template <> template void serde::Serializable::serialize(const Program::BlockType::CallData& obj, Serializer& serializer) -{} +{ + serde::Serializable::serialize(obj.value, serializer); +} template <> template @@ -5612,6 +5619,7 @@ Program::BlockType::CallData serde::Deserializable Deserializer& deserializer) { Program::BlockType::CallData obj; + obj.value = serde::Deserializable::deserialize(deserializer); return obj; } diff --git a/noir/noir-repo/acvm-repo/acir/codegen/acir.cpp b/noir/noir-repo/acvm-repo/acir/codegen/acir.cpp index 232b3ba12cf..b16baf14d06 100644 --- a/noir/noir-repo/acvm-repo/acir/codegen/acir.cpp +++ b/noir/noir-repo/acvm-repo/acir/codegen/acir.cpp @@ -1042,6 +1042,8 @@ namespace Program { }; struct CallData { + uint32_t value; + friend bool operator==(const CallData&, const CallData&); std::vector bincodeSerialize() const; static CallData bincodeDeserialize(std::vector); @@ -4683,6 +4685,7 @@ Program::BlockType::Memory serde::Deserializable::de namespace Program { inline bool operator==(const BlockType::CallData &lhs, const BlockType::CallData &rhs) { + if (!(lhs.value == rhs.value)) { return false; } return true; } @@ -4706,12 +4709,14 @@ namespace Program { template <> template void serde::Serializable::serialize(const Program::BlockType::CallData &obj, Serializer &serializer) { + serde::Serializable::serialize(obj.value, serializer); } template <> template Program::BlockType::CallData serde::Deserializable::deserialize(Deserializer &deserializer) { Program::BlockType::CallData obj; + obj.value = serde::Deserializable::deserialize(deserializer); return obj; } diff --git a/noir/noir-repo/acvm-repo/acir/src/circuit/opcodes.rs b/noir/noir-repo/acvm-repo/acir/src/circuit/opcodes.rs index d303f9fbbab..fbd47de37b7 100644 --- a/noir/noir-repo/acvm-repo/acir/src/circuit/opcodes.rs +++ b/noir/noir-repo/acvm-repo/acir/src/circuit/opcodes.rs @@ -15,13 +15,13 @@ pub use memory_operation::{BlockId, MemOp}; #[derive(Clone, PartialEq, Eq, Serialize, Deserialize)] pub enum BlockType { Memory, - CallData, + CallData(u32), ReturnData, } impl BlockType { pub fn is_databus(&self) -> bool { - matches!(self, BlockType::CallData | BlockType::ReturnData) + matches!(self, BlockType::CallData(_) | BlockType::ReturnData) } } @@ -183,7 +183,7 @@ impl std::fmt::Display for Opcode { Opcode::MemoryInit { block_id, init, block_type: databus } => { match databus { BlockType::Memory => write!(f, "INIT ")?, - BlockType::CallData => write!(f, "INIT CALLDATA ")?, + BlockType::CallData(id) => write!(f, "INIT CALLDATA {} ", id)?, BlockType::ReturnData => write!(f, "INIT RETURNDATA ")?, } write!(f, "(id: {}, len: {}) ", block_id.0, init.len()) diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs index 0e4bbbf759c..c93cea835ea 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs @@ -1722,10 +1722,10 @@ impl<'a> Context<'a> { { databus = BlockType::ReturnData; } - for array_id in self.data_bus.call_data_array() { + for (call_data_id, array_id) in self.data_bus.call_data_array() { if self.block_id(&array_id) == array { assert!(databus == BlockType::Memory); - databus = BlockType::CallData; + databus = BlockType::CallData(call_data_id); break; } } diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/function_builder/data_bus.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/function_builder/data_bus.rs index 3cc9e19376e..6ef3d66d7e4 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/function_builder/data_bus.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/function_builder/data_bus.rs @@ -17,11 +17,13 @@ pub(crate) enum DatabusVisibility { } /// Used to create a data bus, which is an array of private inputs /// replacing public inputs +#[derive(Clone, Debug)] pub(crate) struct DataBusBuilder { pub(crate) values: im::Vector, index: usize, pub(crate) map: HashMap, pub(crate) databus: Option, + call_data_id: Option, } impl DataBusBuilder { @@ -31,6 +33,7 @@ impl DataBusBuilder { map: HashMap::default(), databus: None, values: im::Vector::new(), + call_data_id: None, } } @@ -54,6 +57,8 @@ impl DataBusBuilder { #[derive(Clone, Debug)] pub(crate) struct CallData { + /// The id to this calldata assigned by the user + pub(crate) call_data_id: u32, pub(crate) array_id: ValueId, pub(crate) index_map: HashMap, } @@ -75,14 +80,18 @@ impl DataBus { for (k, v) in cd.index_map.iter() { call_data_map.insert(f(*k), *v); } - CallData { array_id: f(cd.array_id), index_map: call_data_map } + CallData { + array_id: f(cd.array_id), + index_map: call_data_map, + call_data_id: cd.call_data_id, + } }) .collect(); DataBus { call_data, return_data: self.return_data.map(&mut f) } } - pub(crate) fn call_data_array(&self) -> Vec { - self.call_data.iter().map(|cd| cd.array_id).collect() + pub(crate) fn call_data_array(&self) -> Vec<(u32, ValueId)> { + self.call_data.iter().map(|cd| (cd.call_data_id, cd.array_id)).collect() } /// Construct a databus from call_data and return_data data bus builders pub(crate) fn get_data_bus( @@ -91,9 +100,10 @@ impl DataBus { ) -> DataBus { let mut call_data_args = Vec::new(); for call_data_item in call_data { - if let Some(array_id) = call_data_item.databus { - call_data_args.push(CallData { array_id, index_map: call_data_item.map }); - } + let array_id = call_data_item.databus.expect("Call data should have an array id"); + let call_data_id = + call_data_item.call_data_id.expect("Call data should have a user id"); + call_data_args.push(CallData { array_id, call_data_id, index_map: call_data_item.map }); } DataBus { call_data: call_data_args, return_data: return_data.databus } @@ -136,6 +146,7 @@ impl FunctionBuilder { &mut self, values: &[ValueId], mut databus: DataBusBuilder, + call_data_id: Option, ) -> DataBusBuilder { for value in values { self.add_to_data_bus(*value, &mut databus); @@ -150,7 +161,13 @@ impl FunctionBuilder { None }; - DataBusBuilder { index: 0, map: databus.map, databus: array, values: im::Vector::new() } + DataBusBuilder { + index: 0, + map: databus.map, + databus: array, + values: im::Vector::new(), + call_data_id, + } } /// Generate the data bus for call-data, based on the parameters of the entry block @@ -186,7 +203,7 @@ impl FunctionBuilder { let mut result = Vec::new(); for id in databus_param.keys() { let builder = DataBusBuilder::new(); - let call_databus = self.initialize_data_bus(&databus_param[id], builder); + let call_databus = self.initialize_data_bus(&databus_param[id], builder, Some(*id)); result.push(call_databus); } result diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ssa_gen/mod.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ssa_gen/mod.rs index 468a8573307..1373d1bc46e 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ssa_gen/mod.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ssa_gen/mod.rs @@ -83,8 +83,11 @@ pub(crate) fn generate_ssa( _ => unreachable!("ICE - expect return on the last block"), }; - return_data = - function_context.builder.initialize_data_bus(&return_data_values, return_data); + return_data = function_context.builder.initialize_data_bus( + &return_data_values, + return_data, + None, + ); } let return_instruction = function_context.builder.current_function.dfg[block].unwrap_terminator_mut();