diff --git a/acvm-repo/acir/src/circuit/mod.rs b/acvm-repo/acir/src/circuit/mod.rs index 3401867680d..b383aa64ca6 100644 --- a/acvm-repo/acir/src/circuit/mod.rs +++ b/acvm-repo/acir/src/circuit/mod.rs @@ -545,7 +545,7 @@ mod tests { return values: [w2] ASSERT 0 = 2*w1 + 8 BLACKBOX::RANGE input: w1, bits: 8 - BLACKBOX::AND inputs: [w1, w2], bits: 4, output: w3 + BLACKBOX::AND lhs: w1, rhs: w2, output: w3, bits: 4 BLACKBOX::KECCAKF1600 inputs: [w1, w2, w3, w4, w5, w6, w7, w8, w9, w10, w11, w12, w13, w14, w15, w16, w17, w18, w19, w20, w21, w22, w23, w24, w25], outputs: [w26, w27, w28, w29, w30, w31, w32, w33, w34, w35, w36, w37, w38, w39, w40, w41, w42, w43, w44, w45, w46, w47, w48, w49, w50] " ); diff --git a/acvm-repo/acir/src/circuit/opcodes.rs b/acvm-repo/acir/src/circuit/opcodes.rs index cb57e21f7c3..a5ed4b2e393 100644 --- a/acvm-repo/acir/src/circuit/opcodes.rs +++ b/acvm-repo/acir/src/circuit/opcodes.rs @@ -258,7 +258,7 @@ mod tests { insta::assert_snapshot!( xor.to_string(), - @"BLACKBOX::XOR inputs: [w0, w1], bits: 32, output: w3" + @"BLACKBOX::XOR lhs: w0, rhs: w1, output: w3, bits: 32" ); } diff --git a/acvm-repo/acir/src/circuit/opcodes/black_box_function_call.rs b/acvm-repo/acir/src/circuit/opcodes/black_box_function_call.rs index 287c4fa44d6..d62c19140e0 100644 --- a/acvm-repo/acir/src/circuit/opcodes/black_box_function_call.rs +++ b/acvm-repo/acir/src/circuit/opcodes/black_box_function_call.rs @@ -435,29 +435,101 @@ impl std::fmt::Display for BlackBoxFuncCall { let uppercase_name = self.name().to_uppercase(); write!(f, "BLACKBOX::{uppercase_name} ")?; - // inputs - let inputs = &self.get_inputs_vec(); - let inputs_str = inputs.iter().map(|i| i.to_string()).collect::>().join(", "); - if inputs.len() == 1 { - write!(f, "input: {inputs_str}")?; - } else { - write!(f, "inputs: [{inputs_str}]")?; - } - - // bits - if let Some(bit_size) = self.bit_size() { - write!(f, ", bits: {bit_size}")?; - } - - // outputs - let outputs = &self.get_outputs_vec(); - if !outputs.is_empty() { - let outputs_str = - outputs.iter().map(ToString::to_string).collect::>().join(", "); - if outputs.len() == 1 { - write!(f, ", output: {outputs_str}")?; - } else { - write!(f, ", outputs: [{outputs_str}]")?; + match self { + BlackBoxFuncCall::AES128Encrypt { inputs, iv, key, outputs } => { + let inputs = slice_to_string(inputs); + let iv = slice_to_string(&iv.to_vec()); + let key = slice_to_string(&key.to_vec()); + let outputs = slice_to_string(outputs); + write!(f, "inputs: {inputs}, iv: {iv}, key: {key}, outputs: {outputs}")?; + } + BlackBoxFuncCall::AND { lhs, rhs, num_bits, output } + | BlackBoxFuncCall::XOR { lhs, rhs, num_bits, output } => { + write!(f, "lhs: {lhs}, rhs: {rhs}, output: {output}, bits: {num_bits}")?; + } + BlackBoxFuncCall::RANGE { input, num_bits } => { + write!(f, "input: {input}, bits: {num_bits}")?; + } + BlackBoxFuncCall::Blake2s { inputs, outputs } + | BlackBoxFuncCall::Blake3 { inputs, outputs } => { + let inputs = slice_to_string(inputs); + let outputs = slice_to_string(&outputs.to_vec()); + write!(f, "inputs: {inputs}, outputs: {outputs}")?; + } + BlackBoxFuncCall::EcdsaSecp256k1 { + public_key_x, + public_key_y, + signature, + hashed_message, + predicate, + output, + } + | BlackBoxFuncCall::EcdsaSecp256r1 { + public_key_x, + public_key_y, + signature, + hashed_message, + predicate, + output, + } => { + let public_key_x = slice_to_string(&public_key_x.to_vec()); + let public_key_y = slice_to_string(&public_key_y.to_vec()); + let signature = slice_to_string(&signature.to_vec()); + let hashed_message = slice_to_string(&hashed_message.to_vec()); + write!( + f, + "public_key_x: {public_key_x}, public_key_y: {public_key_y}, signature: {signature}, hashed_message: {hashed_message}, predicate: {predicate}, output: {output}" + )?; + } + BlackBoxFuncCall::MultiScalarMul { points, scalars, predicate, outputs } => { + let points = slice_to_string(points); + let scalars = slice_to_string(scalars); + write!( + f, + "points: {points}, scalars: {scalars}, predicate: {predicate}, outputs: [{}, {}, {}]", + outputs.0, outputs.1, outputs.2 + )?; + } + BlackBoxFuncCall::EmbeddedCurveAdd { input1, input2, predicate, outputs } => { + let input1 = slice_to_string(&input1.to_vec()); + let input2 = slice_to_string(&input2.to_vec()); + write!( + f, + "input1: {input1}, input2: {input2}, predicate: {predicate}, outputs: [{}, {}, {}]", + outputs.0, outputs.1, outputs.2 + )?; + } + BlackBoxFuncCall::Keccakf1600 { inputs, outputs } => { + let inputs = slice_to_string(&inputs.to_vec()); + let outputs = slice_to_string(&outputs.to_vec()); + write!(f, "inputs: {inputs}, outputs: {outputs}")?; + } + BlackBoxFuncCall::RecursiveAggregation { + verification_key, + proof, + public_inputs, + key_hash, + proof_type, + predicate, + } => { + let verification_key = slice_to_string(verification_key); + let proof = slice_to_string(proof); + let public_inputs = slice_to_string(public_inputs); + write!( + f, + "verification_key: {verification_key}, proof: {proof}, public_inputs: {public_inputs}, key_hash: {key_hash}, proof_type: {proof_type}, predicate: {predicate}" + )?; + } + BlackBoxFuncCall::Poseidon2Permutation { inputs, outputs } => { + let inputs = slice_to_string(inputs); + let outputs = slice_to_string(outputs); + write!(f, "inputs: {inputs}, outputs: {outputs}")?; + } + BlackBoxFuncCall::Sha256Compression { inputs, hash_values, outputs } => { + let inputs = slice_to_string(&inputs.to_vec()); + let hash_values = slice_to_string(&hash_values.to_vec()); + let outputs = slice_to_string(&outputs.to_vec()); + write!(f, "inputs: {inputs}, hash_values: {hash_values}, outputs: {outputs}")?; } } @@ -465,6 +537,11 @@ impl std::fmt::Display for BlackBoxFuncCall { } } +fn slice_to_string(inputs: &[D]) -> String { + let inputs = inputs.iter().map(|i| i.to_string()).collect::>().join(", "); + format!("[{inputs}]") +} + impl std::fmt::Debug for BlackBoxFuncCall { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { std::fmt::Display::fmt(self, f) diff --git a/acvm-repo/acir/src/parser/mod.rs b/acvm-repo/acir/src/parser/mod.rs index 75914231318..6a1ea14411c 100644 --- a/acvm-repo/acir/src/parser/mod.rs +++ b/acvm-repo/acir/src/parser/mod.rs @@ -258,7 +258,7 @@ impl<'a> Parser<'a> { } fn parse_assert_zero_expression(&mut self) -> ParseResult> { - // 'CONSTRAIN' + // 'ASSERT' self.eat_keyword_or_error(Keyword::Assert)?; // Parse the left-hand side terms @@ -343,7 +343,6 @@ impl<'a> Parser<'a> { Ok(expression) } - // TODO: Convert all assertions on input/output lengths to real errors fn parse_blackbox_func_call(&mut self) -> ParseResult> { self.eat_keyword(Keyword::BlackBoxFuncCall)?; self.eat_or_error(Token::Colon)?; @@ -361,64 +360,88 @@ impl<'a> Parser<'a> { let func = match func_name { BlackBoxFunc::AES128Encrypt => { - let mut inputs = self.parse_blackbox_inputs()?; + let inputs = self.parse_blackbox_inputs(Keyword::Inputs)?; + self.eat_comma_or_error()?; - let key = self.try_extract_tail::<16, _>(&mut inputs, "key")?; - let iv = self.try_extract_tail::<16, _>(&mut inputs, "IV")?; + let iv = self.parse_blackbox_inputs_array::<16>(Keyword::Iv)?; + self.eat_comma_or_error()?; + + let key = self.parse_blackbox_inputs_array::<16>(Keyword::Key)?; + self.eat_comma_or_error()?; let outputs = self.parse_blackbox_outputs()?; BlackBoxFuncCall::AES128Encrypt { inputs, iv, key, outputs } } BlackBoxFunc::AND => { - let inputs = self.parse_blackbox_inputs()?; - self.expect_len(&inputs, 2, "AND", false)?; + let lhs = self.parse_blackbox_input(Keyword::Lhs)?; + self.eat_comma_or_error()?; + + let rhs = self.parse_blackbox_input(Keyword::Rhs)?; + self.eat_comma_or_error()?; - let num_bits = self.parse_blackbox_bit_size()?; let output = self.parse_blackbox_output()?; + self.eat_comma_or_error()?; + + let num_bits = self.parse_blackbox_u32(Keyword::Bits)?; - BlackBoxFuncCall::AND { lhs: inputs[0], rhs: inputs[1], num_bits, output } + BlackBoxFuncCall::AND { lhs, rhs, num_bits, output } } BlackBoxFunc::XOR => { - let inputs = self.parse_blackbox_inputs()?; - self.expect_len(&inputs, 2, "XOR", false)?; + let lhs = self.parse_blackbox_input(Keyword::Lhs)?; + self.eat_comma_or_error()?; + + let rhs = self.parse_blackbox_input(Keyword::Rhs)?; + self.eat_comma_or_error()?; - let num_bits = self.parse_blackbox_bit_size()?; let output = self.parse_blackbox_output()?; + self.eat_comma_or_error()?; + + let num_bits = self.parse_blackbox_u32(Keyword::Bits)?; - BlackBoxFuncCall::XOR { lhs: inputs[0], rhs: inputs[1], num_bits, output } + BlackBoxFuncCall::XOR { lhs, rhs, num_bits, output } } BlackBoxFunc::RANGE => { - self.eat_keyword_or_error(Keyword::Input)?; - self.eat_or_error(Token::Colon)?; - let input = self.parse_blackbox_input()?; - let num_bits = self.parse_blackbox_bit_size()?; + let input = self.parse_blackbox_input(Keyword::Input)?; + self.eat_comma_or_error()?; + + let num_bits = self.parse_blackbox_u32(Keyword::Bits)?; BlackBoxFuncCall::RANGE { input, num_bits } } BlackBoxFunc::Blake2s => { - let inputs = self.parse_blackbox_inputs()?; - let outputs = self.parse_blackbox_outputs()?; - let outputs = self.try_vec_to_array::<32, _>(outputs, "Blake2s", true)?; + let inputs = self.parse_blackbox_inputs(Keyword::Inputs)?; + self.eat_comma_or_error()?; + + let outputs = self.parse_blackbox_outputs_array::<32>()?; BlackBoxFuncCall::Blake2s { inputs, outputs } } BlackBoxFunc::Blake3 => { - let inputs = self.parse_blackbox_inputs()?; - let outputs = self.parse_blackbox_outputs()?; - let outputs = self.try_vec_to_array::<32, _>(outputs, "Blake3", true)?; + let inputs = self.parse_blackbox_inputs(Keyword::Inputs)?; + self.eat_comma_or_error()?; + + let outputs = self.parse_blackbox_outputs_array::<32>()?; BlackBoxFuncCall::Blake3 { inputs, outputs } } BlackBoxFunc::EcdsaSecp256k1 => { - let mut inputs = self.parse_blackbox_inputs()?; + let public_key_x = self.parse_blackbox_inputs_array::<32>(Keyword::PublicKeyX)?; + self.eat_comma_or_error()?; + + let public_key_y = self.parse_blackbox_inputs_array::<32>(Keyword::PublicKeyY)?; + self.eat_comma_or_error()?; + + let signature = self.parse_blackbox_inputs_array::<64>(Keyword::Signature)?; + self.eat_comma_or_error()?; - let predicate = self.try_extract_tail::<1, _>(&mut inputs, "predicate")?[0]; let hashed_message = - self.try_extract_tail::<32, _>(&mut inputs, "hashed_message")?; - let signature = self.try_extract_tail::<64, _>(&mut inputs, "signature")?; - let public_key_y = self.try_extract_tail::<32, _>(&mut inputs, "public_key_y")?; - let public_key_x = self.try_extract_tail::<32, _>(&mut inputs, "public_key_x")?; + self.parse_blackbox_inputs_array::<32>(Keyword::HashedMessage)?; + self.eat_comma_or_error()?; + + let predicate = self.parse_blackbox_input(Keyword::Predicate)?; + self.eat_comma_or_error()?; + let output = self.parse_blackbox_output()?; BlackBoxFuncCall::EcdsaSecp256k1 { @@ -431,14 +454,22 @@ impl<'a> Parser<'a> { } } BlackBoxFunc::EcdsaSecp256r1 => { - let mut inputs = self.parse_blackbox_inputs()?; + let public_key_x = self.parse_blackbox_inputs_array::<32>(Keyword::PublicKeyX)?; + self.eat_comma_or_error()?; + + let public_key_y = self.parse_blackbox_inputs_array::<32>(Keyword::PublicKeyY)?; + self.eat_comma_or_error()?; + + let signature = self.parse_blackbox_inputs_array::<64>(Keyword::Signature)?; + self.eat_comma_or_error()?; - let predicate = self.try_extract_tail::<1, _>(&mut inputs, "predicate")?[0]; let hashed_message = - self.try_extract_tail::<32, _>(&mut inputs, "hashed_message")?; - let signature = self.try_extract_tail::<64, _>(&mut inputs, "signature")?; - let public_key_y = self.try_extract_tail::<32, _>(&mut inputs, "public_key_y")?; - let public_key_x = self.try_extract_tail::<32, _>(&mut inputs, "public_key_x")?; + self.parse_blackbox_inputs_array::<32>(Keyword::HashedMessage)?; + self.eat_comma_or_error()?; + + let predicate = self.parse_blackbox_input(Keyword::Predicate)?; + self.eat_comma_or_error()?; + let output = self.parse_blackbox_output()?; BlackBoxFuncCall::EcdsaSecp256r1 { @@ -450,48 +481,87 @@ impl<'a> Parser<'a> { predicate, } } - BlackBoxFunc::MultiScalarMul => todo!(), + BlackBoxFunc::MultiScalarMul => { + let points = self.parse_blackbox_inputs(Keyword::Points)?; + self.eat_comma_or_error()?; + + let scalars = self.parse_blackbox_inputs(Keyword::Scalars)?; + self.eat_comma_or_error()?; + + let predicate = self.parse_blackbox_input(Keyword::Predicate)?; + self.eat_comma_or_error()?; + + let outputs = self.parse_blackbox_outputs_array::<3>()?; + let outputs = (outputs[0], outputs[1], outputs[2]); + + BlackBoxFuncCall::MultiScalarMul { points, scalars, predicate, outputs } + } BlackBoxFunc::Keccakf1600 => { - let inputs = self.parse_blackbox_inputs()?; - let inputs = self.try_vec_to_array::<25, _>(inputs, "Keccakf1600 inputs", false)?; - let outputs = self.parse_blackbox_outputs()?; - let outputs = - self.try_vec_to_array::<25, _>(outputs, "Keccakf1600 outputs", true)?; + let inputs = self.parse_blackbox_inputs_array::<25>(Keyword::Inputs)?; + self.eat_comma_or_error()?; + + let outputs = self.parse_blackbox_outputs_array::<25>()?; BlackBoxFuncCall::Keccakf1600 { inputs, outputs } } BlackBoxFunc::RecursiveAggregation => { - todo!("Need to change the format to dictate the size of each of input") - } - BlackBoxFunc::EmbeddedCurveAdd => { - let mut inputs = self.parse_blackbox_inputs()?; - let predicate = self.try_extract_tail::<1, _>(&mut inputs, "predicate")?[0]; - let input2 = self.try_extract_tail::<3, _>(&mut inputs, "EC add input2")?; - let input1 = self.try_extract_tail::<3, _>(&mut inputs, "EC add input1")?; - let outputs = self.parse_blackbox_outputs()?; - self.expect_len(&outputs, 3, "EmbeddedCurveAdd", true)?; + let verification_key = self.parse_blackbox_inputs(Keyword::VerificationKey)?; + self.eat_comma_or_error()?; + + let proof = self.parse_blackbox_inputs(Keyword::Proof)?; + self.eat_comma_or_error()?; + + let public_inputs = self.parse_blackbox_inputs(Keyword::PublicInputs)?; + self.eat_comma_or_error()?; + + let key_hash = self.parse_blackbox_input(Keyword::KeyHash)?; + self.eat_comma_or_error()?; + + let proof_type = self.parse_blackbox_u32(Keyword::ProofType)?; + self.eat_comma_or_error()?; + + let predicate = self.parse_blackbox_input(Keyword::Predicate)?; - BlackBoxFuncCall::EmbeddedCurveAdd { - input1, - input2, + BlackBoxFuncCall::RecursiveAggregation { + verification_key, + proof, + public_inputs, + key_hash, + proof_type, predicate, - outputs: (outputs[0], outputs[1], outputs[2]), } } + BlackBoxFunc::EmbeddedCurveAdd => { + let input1 = self.parse_blackbox_inputs_array::<3>(Keyword::Input1)?; + self.eat_comma_or_error()?; + + let input2 = self.parse_blackbox_inputs_array::<3>(Keyword::Input2)?; + self.eat_comma_or_error()?; + + let predicate = self.parse_blackbox_input(Keyword::Predicate)?; + self.eat_comma_or_error()?; + + let outputs = self.parse_blackbox_outputs_array::<3>()?; + let outputs = (outputs[0], outputs[1], outputs[2]); + + BlackBoxFuncCall::EmbeddedCurveAdd { input1, input2, predicate, outputs } + } BlackBoxFunc::Poseidon2Permutation => { - let inputs = self.parse_blackbox_inputs()?; + let inputs = self.parse_blackbox_inputs(Keyword::Inputs)?; + self.eat_comma_or_error()?; + let outputs = self.parse_blackbox_outputs()?; + BlackBoxFuncCall::Poseidon2Permutation { inputs, outputs } } BlackBoxFunc::Sha256Compression => { - let mut inputs = self.parse_blackbox_inputs()?; + let inputs = self.parse_blackbox_inputs_array::<16>(Keyword::Inputs)?; + self.eat_comma_or_error()?; - let hash_values = self.try_extract_tail::<8, _>(&mut inputs, "hash_values")?; - let inputs = self.try_extract_tail::<16, _>(&mut inputs, "inputs")?; + let hash_values = self.parse_blackbox_inputs_array::<8>(Keyword::HashValues)?; + self.eat_comma_or_error()?; - let outputs = self.parse_blackbox_outputs()?; - let outputs = - self.try_vec_to_array::<8, _>(outputs, "Sha256Compression outputs", true)?; + let outputs = self.parse_blackbox_outputs_array::<8>()?; BlackBoxFuncCall::Sha256Compression { inputs, hash_values, outputs } } @@ -499,15 +569,26 @@ impl<'a> Parser<'a> { Ok(func) } - fn parse_blackbox_inputs(&mut self) -> ParseResult>> { - self.eat_keyword_or_error(Keyword::Inputs)?; + fn parse_blackbox_inputs_array( + &mut self, + keyword: Keyword, + ) -> Result; N]>, ParserError> { + let inputs = self.parse_blackbox_inputs(keyword)?; + self.try_vec_to_array::(inputs, keyword) + } + + fn parse_blackbox_inputs( + &mut self, + keyword: Keyword, + ) -> ParseResult>> { + self.eat_keyword_or_error(keyword)?; self.eat_or_error(Token::Colon)?; self.eat_or_error(Token::LeftBracket)?; let mut inputs = Vec::new(); while !self.eat(Token::RightBracket)? { - let input = self.parse_blackbox_input()?; + let input = self.parse_blackbox_input_no_keyword()?; inputs.push(input); // Eat a comma if there is another input, but do not error if there is no comma @@ -518,7 +599,18 @@ impl<'a> Parser<'a> { Ok(inputs) } - fn parse_blackbox_input(&mut self) -> Result, ParserError> { + fn parse_blackbox_input( + &mut self, + keyword: Keyword, + ) -> Result, ParserError> { + self.eat_keyword_or_error(keyword)?; + self.eat_or_error(Token::Colon)?; + self.parse_blackbox_input_no_keyword() + } + + fn parse_blackbox_input_no_keyword( + &mut self, + ) -> Result, ParserError> { Ok(match self.token.token() { Token::Int(value) => { let value = *value; @@ -541,23 +633,25 @@ impl<'a> Parser<'a> { } fn parse_blackbox_output(&mut self) -> ParseResult { - self.eat_or_error(Token::Comma)?; self.eat_keyword_or_error(Keyword::Output)?; self.eat_or_error(Token::Colon)?; let witness = self.eat_witness_or_error()?; Ok(witness) } + fn parse_blackbox_outputs_array(&mut self) -> ParseResult> { + let outputs = self.parse_blackbox_outputs()?; + self.try_vec_to_array::(outputs, Keyword::Outputs) + } + fn parse_blackbox_outputs(&mut self) -> ParseResult> { - self.eat_or_error(Token::Comma)?; self.eat_keyword_or_error(Keyword::Outputs)?; self.eat_or_error(Token::Colon)?; self.parse_witness_vector() } - fn parse_blackbox_bit_size(&mut self) -> ParseResult { - self.eat_or_error(Token::Comma)?; - self.eat_keyword_or_error(Keyword::Bits)?; + fn parse_blackbox_u32(&mut self, keyword: Keyword) -> ParseResult { + self.eat_keyword_or_error(keyword)?; self.eat_or_error(Token::Colon)?; let num_bits = self.eat_u32_or_error()?; @@ -860,6 +954,10 @@ impl<'a> Parser<'a> { if let Some(int) = self.eat_block_id()? { Ok(int) } else { self.expected_block_id() } } + fn eat_comma_or_error(&mut self) -> ParseResult<()> { + self.eat_or_error(Token::Comma) + } + fn eat_or_error(&mut self, token: Token) -> ParseResult<()> { if self.eat(token.clone())? { Ok(()) } else { self.expected_token(token) } } @@ -875,80 +973,17 @@ impl<'a> Parser<'a> { } } - fn expect_len( - &self, - items: &[T], - expected: usize, - name: &str, - is_output: bool, - ) -> Result<(), ParserError> { - if items.len() != expected { - if is_output { - Err(ParserError::IncorrectOutputLength { - expected, - found: items.len(), - name: name.to_owned(), - span: self.token.span(), - }) - } else { - Err(ParserError::IncorrectInputLength { - expected, - found: items.len(), - name: name.to_owned(), - span: self.token.span(), - }) - } - } else { - Ok(()) - } - } - - fn try_extract_tail( - &self, - items: &mut Vec, - name: &str, - ) -> Result, ParserError> { - if items.len() < N { - return Err(ParserError::IncorrectInputLength { - expected: N, - found: items.len(), - name: name.to_owned(), - span: self.token.span(), - }); - } - let extracted = items.split_off(items.len() - N); - let len = extracted.len(); - extracted.try_into().map_err(|_| ParserError::IncorrectInputLength { - expected: N, - found: len, - name: name.to_owned(), - span: self.token.span(), - }) - } - fn try_vec_to_array( &self, vec: Vec, - name: &str, - is_output: bool, + keyword: Keyword, ) -> Result, ParserError> { let len = vec.len(); - vec.try_into().map_err(|_| { - if is_output { - ParserError::IncorrectOutputLength { - expected: N, - found: len, - name: name.to_owned(), - span: self.token.span(), - } - } else { - ParserError::IncorrectInputLength { - expected: N, - found: len, - name: name.to_owned(), - span: self.token.span(), - } - } + vec.try_into().map_err(|_| ParserError::IncorrectValuesLength { + expected: N, + found: len, + name: keyword.to_string(), + span: self.token.span(), }) } @@ -1070,10 +1105,8 @@ pub(crate) enum ParserError { ExpectedBlackBoxFuncName { found: Token, span: Span }, #[error("Number does not fit in u32, got: '{number}'")] IntegerLargerThanU32 { number: FieldElement, span: Span }, - #[error("Expected {expected} inputs for {name}, found {found}")] - IncorrectInputLength { expected: usize, found: usize, name: String, span: Span }, - #[error("Expected {expected} outputs for {name}, found {found}")] - IncorrectOutputLength { expected: usize, found: usize, name: String, span: Span }, + #[error("Expected {expected} values for {name}, found {found}")] + IncorrectValuesLength { expected: usize, found: usize, name: String, span: Span }, #[error("Expected function id {expected}, found {found}")] UnexpectedFunctionId { expected: u32, found: u32, span: Span }, } @@ -1092,8 +1125,7 @@ impl ParserError { | ExpectedTerm { span, .. } | ExpectedBlackBoxFuncName { span, .. } | IntegerLargerThanU32 { span, .. } - | IncorrectInputLength { span, .. } - | IncorrectOutputLength { span, .. } + | IncorrectValuesLength { span, .. } | UnexpectedFunctionId { span, .. } => *span, } } diff --git a/acvm-repo/acir/src/parser/tests.rs b/acvm-repo/acir/src/parser/tests.rs index 080425680ab..06f45c33364 100644 --- a/acvm-repo/acir/src/parser/tests.rs +++ b/acvm-repo/acir/src/parser/tests.rs @@ -135,6 +135,20 @@ fn range_check() { assert_circuit_roundtrip(src); } +#[test] +fn and() { + let src = " + private parameters: [w0] + public parameters: [w1] + return values: [] + BLACKBOX::RANGE input: w0, bits: 32 + BLACKBOX::RANGE input: w1, bits: 32 + BLACKBOX::AND lhs: w0, rhs: w1, output: w2, bits: 32 + ASSERT w2 = 15 + "; + assert_circuit_roundtrip(src); +} + #[test] fn xor() { let src = " @@ -143,7 +157,7 @@ fn xor() { return values: [] BLACKBOX::RANGE input: w0, bits: 32 BLACKBOX::RANGE input: w1, bits: 32 - BLACKBOX::XOR inputs: [w0, w1], bits: 32, output: w2 + BLACKBOX::XOR lhs: w0, rhs: w1, output: w2, bits: 32 ASSERT w2 = 15 "; assert_circuit_roundtrip(src); @@ -216,7 +230,7 @@ fn aes128_encrypt() { BLACKBOX::RANGE input: w57, bits: 8 BLACKBOX::RANGE input: w58, bits: 8 BLACKBOX::RANGE input: w59, bits: 8 - BLACKBOX::AES128_ENCRYPT inputs: [w12, w13, w14, w15, w16, w17, w18, w19, w20, w21, w22, w23, w24, w25, w26, w27, w28, w29, w30, w31, w32, w33, w34, w35, w36, w37, w38, w39, w40, w41, w42, w43], outputs: [w60, w61, w62, w63, w64, w65, w66, w67, w68, w69, w70, w71, w72, w73, w74, w75] + BLACKBOX::AES128_ENCRYPT inputs: [w0, w1, w2, w3, w4, w5, w6, w7, w8, w9, w10, w11, w12, w13, w14, w15, w16, w17, w18, w19, w20, w21, w22, w23, w24, w25, w26, w27], iv: [w28, w29, w30, w31, w32, w33, w34, w35, w36, w37, w38, w39, w40, w41, w42, w43], key: [w44, w45, w46, w47, w48, w49, w50, w51, w52, w53, w54, w55, w56, w57, w58, w59], outputs: [w60, w61, w62, w63, w64, w65, w66, w67, w68, w69, w70, w71, w72, w73, w74, w75] ASSERT w60 = w44 ASSERT w61 = w45 ASSERT w62 = w46 @@ -261,32 +275,36 @@ fn blake3() { #[test] fn ecdsa_secp256k1() { - let input_witnesses: Vec = (0..161).map(|i| format!("w{i}")).collect(); - let inputs_str = input_witnesses.join(", "); + let public_key_x = (0..32).map(|i| format!("w{i}")).collect::>().join(", "); + let public_key_y = (32..64).map(|i| format!("w{i}")).collect::>().join(", "); + let signature = (64..128).map(|i| format!("w{i}")).collect::>().join(", "); + let hashed_message = (128..160).map(|i| format!("w{i}")).collect::>().join(", "); let src = format!( - " + " private parameters: [] public parameters: [] return values: [] - BLACKBOX::ECDSA_SECP256K1 inputs: [{inputs_str}], output: w161 + BLACKBOX::ECDSA_SECP256K1 public_key_x: [{public_key_x}], public_key_y: [{public_key_y}], signature: [{signature}], hashed_message: [{hashed_message}], predicate: 1, output: w161 " ); assert_circuit_roundtrip(&src); } #[test] -#[should_panic = "Expected 32 inputs for public_key_y, found 3"] +#[should_panic = "Expected 32 values for public_key_x, found 31"] fn ecdsa_secp256k1_missing_inputs() { - let input_witnesses: Vec = (0..100).map(|i| format!("w{i}")).collect(); - let inputs_str = input_witnesses.join(", "); + let public_key_x = (0..31).map(|i| format!("w{i}")).collect::>().join(", "); + let public_key_y = (32..64).map(|i| format!("w{i}")).collect::>().join(", "); + let signature = (64..128).map(|i| format!("w{i}")).collect::>().join(", "); + let hashed_message = (128..160).map(|i| format!("w{i}")).collect::>().join(", "); let src = format!( - " + " private parameters: [] public parameters: [] return values: [] - BLACKBOX::ECDSA_SECP256K1 inputs: [{inputs_str}], output: w100 + BLACKBOX::ECDSA_SECP256K1 public_key_x: [{public_key_x}], public_key_y: [{public_key_y}], signature: [{signature}], hashed_message: [{hashed_message}], predicate: 1, output: w161 " ); let _ = Circuit::from_str(&src).unwrap(); @@ -294,32 +312,36 @@ fn ecdsa_secp256k1_missing_inputs() { #[test] fn ecdsa_secp256r1() { - let input_witnesses: Vec = (0..161).map(|i| format!("w{i}")).collect(); - let inputs_str = input_witnesses.join(", "); + let public_key_x = (0..32).map(|i| format!("w{i}")).collect::>().join(", "); + let public_key_y = (32..64).map(|i| format!("w{i}")).collect::>().join(", "); + let signature = (64..128).map(|i| format!("w{i}")).collect::>().join(", "); + let hashed_message = (128..160).map(|i| format!("w{i}")).collect::>().join(", "); let src = format!( - " + " private parameters: [] public parameters: [] return values: [] - BLACKBOX::ECDSA_SECP256R1 inputs: [{inputs_str}], output: w161 + BLACKBOX::ECDSA_SECP256R1 public_key_x: [{public_key_x}], public_key_y: [{public_key_y}], signature: [{signature}], hashed_message: [{hashed_message}], predicate: 1, output: w161 " ); assert_circuit_roundtrip(&src); } #[test] -#[should_panic = "Expected 32 inputs for public_key_y, found 3"] +#[should_panic = "Expected 64 values for signature, found 30"] fn ecdsa_secp256r1_missing_inputs() { - let input_witnesses: Vec = (0..100).map(|i| format!("w{i}")).collect(); - let inputs_str = input_witnesses.join(", "); + let public_key_x = (0..32).map(|i| format!("w{i}")).collect::>().join(", "); + let public_key_y = (32..64).map(|i| format!("w{i}")).collect::>().join(", "); + let signature = (64..94).map(|i| format!("w{i}")).collect::>().join(", "); + let hashed_message = (128..160).map(|i| format!("w{i}")).collect::>().join(", "); let src = format!( - " + " private parameters: [] public parameters: [] return values: [] - BLACKBOX::ECDSA_SECP256R1 inputs: [{inputs_str}], outputs: [w100] + BLACKBOX::ECDSA_SECP256R1 public_key_x: [{public_key_x}], public_key_y: [{public_key_y}], signature: [{signature}], hashed_message: [{hashed_message}], predicate: 1, output: w161 " ); let _ = Circuit::from_str(&src).unwrap(); @@ -345,7 +367,7 @@ fn keccakf1600() { } #[test] -#[should_panic = "Expected 25 inputs for Keccakf1600 inputs, found 24"] +#[should_panic = "Expected 25 values for inputs, found 24"] fn keccakf1600_missing_inputs() { let input_witnesses: Vec = (0..24).map(|i| format!("w{i}")).collect(); let inputs_str = input_witnesses.join(", "); @@ -370,7 +392,7 @@ fn embedded_curve_add() { private parameters: [] public parameters: [] return values: [] - BLACKBOX::EMBEDDED_CURVE_ADD inputs: [w0, w1, w2, w3, w4, w5, w6], outputs: [w7, w8, w9] + BLACKBOX::EMBEDDED_CURVE_ADD input1: [w0, w1, w2], input2: [w3, w4, w5], predicate: w6, outputs: [w7, w8, w9] "; assert_circuit_roundtrip(src); } @@ -382,7 +404,7 @@ fn embedded_curve_add_wrong_output_count() { private parameters: [] public parameters: [] return values: [] - BLACKBOX::EMBEDDED_CURVE_ADD inputs: [w0, w1, w2, w3, w4, w5, w6], outputs: [w7, w8] + BLACKBOX::EMBEDDED_CURVE_ADD input1: [w0, w1, w2], input2: [w3, w4, w5], predicate: w6, outputs: [w7, w8] "; let _ = Circuit::from_str(src).unwrap(); } @@ -400,9 +422,12 @@ fn poseidon2_permutation() { #[test] fn sha256_compression() { - let input_witnesses: Vec = (0..24).map(|i| format!("w{i}")).collect(); + let input_witnesses: Vec = (0..16).map(|i| format!("w{i}")).collect(); let inputs_str = input_witnesses.join(", "); + let hash_value_witnesses: Vec = (16..24).map(|i| format!("w{i}")).collect(); + let hash_values_str = hash_value_witnesses.join(", "); + let output_witnesses: Vec = (24..32).map(|i| format!("w{i}")).collect(); let outputs_str = output_witnesses.join(", "); @@ -411,7 +436,7 @@ fn sha256_compression() { private parameters: [] public parameters: [] return values: [] - BLACKBOX::SHA256_COMPRESSION inputs: [{inputs_str}], outputs: [{outputs_str}] + BLACKBOX::SHA256_COMPRESSION inputs: [{inputs_str}], hash_values: [{hash_values_str}], outputs: [{outputs_str}] " ); assert_circuit_roundtrip(&src); @@ -420,9 +445,12 @@ fn sha256_compression() { #[test] #[should_panic] fn sha256_compression_missing_outputs() { - let input_witnesses: Vec = (0..24).map(|i| format!("w{i}")).collect(); + let input_witnesses: Vec = (0..16).map(|i| format!("w{i}")).collect(); let inputs_str = input_witnesses.join(", "); + let hash_value_witnesses: Vec = (16..24).map(|i| format!("w{i}")).collect(); + let hash_values_str = hash_value_witnesses.join(", "); + let output_witnesses: Vec = (24..31).map(|i| format!("w{i}")).collect(); // should be 8 total let outputs_str = output_witnesses.join(", "); @@ -431,12 +459,34 @@ fn sha256_compression_missing_outputs() { private parameters: [] public parameters: [] return values: [] - BLACKBOX::SHA256_COMPRESSION inputs: [{inputs_str}], outputs: [{outputs_str}] + BLACKBOX::SHA256_COMPRESSION inputs: [{inputs_str}], hash_values: [{hash_values_str}], outputs: [{outputs_str}] " ); let _ = Circuit::from_str(&src).unwrap(); } +#[test] +fn multi_scalar_mul() { + let src = " + private parameters: [] + public parameters: [] + return values: [] + BLACKBOX::MULTI_SCALAR_MUL points: [w0, w1], scalars: [w2, w3], predicate: 1, outputs: [w4, w5, w6] + "; + assert_circuit_roundtrip(src); +} + +#[test] +fn recursive_aggregation() { + let src = " + private parameters: [] + public parameters: [] + return values: [] + BLACKBOX::RECURSIVE_AGGREGATION verification_key: [w0], proof: [w1], public_inputs: [w2], key_hash: w3, proof_type: 4, predicate: 1 + "; + assert_circuit_roundtrip(src); +} + #[test] fn memory_read() { let src = " diff --git a/acvm-repo/acir/src/parser/token.rs b/acvm-repo/acir/src/parser/token.rs index a678fde3f6e..9ffb1a5d3e1 100644 --- a/acvm-repo/acir/src/parser/token.rs +++ b/acvm-repo/acir/src/parser/token.rs @@ -134,6 +134,10 @@ pub(crate) enum Keyword { Function, /// input Input, + /// input1 + Input1, + /// input2 + Input2, /// inputs Inputs, /// output @@ -142,6 +146,38 @@ pub(crate) enum Keyword { Outputs, /// bits Bits, + /// iv + Iv, + /// key + Key, + /// lhs + Lhs, + /// rhs + Rhs, + /// public_key_x + PublicKeyX, + /// public_key_y + PublicKeyY, + /// signature + Signature, + /// hashed_message + HashedMessage, + /// points + Points, + /// scalars + Scalars, + /// verification_key + VerificationKey, + /// proof + Proof, + /// public_inputs + PublicInputs, + /// key_hash + KeyHash, + /// proof_type + ProofType, + /// hash_values + HashValues, } impl Keyword { @@ -165,10 +201,28 @@ impl Keyword { "RETURNDATA" => Keyword::ReturnData, "func" => Keyword::Function, "input" => Keyword::Input, + "input1" => Keyword::Input1, + "input2" => Keyword::Input2, "inputs" => Keyword::Inputs, "output" => Keyword::Output, "outputs" => Keyword::Outputs, "bits" => Keyword::Bits, + "iv" => Keyword::Iv, + "key" => Keyword::Key, + "lhs" => Keyword::Lhs, + "rhs" => Keyword::Rhs, + "public_key_x" => Keyword::PublicKeyX, + "public_key_y" => Keyword::PublicKeyY, + "signature" => Keyword::Signature, + "hashed_message" => Keyword::HashedMessage, + "points" => Keyword::Points, + "scalars" => Keyword::Scalars, + "verification_key" => Keyword::VerificationKey, + "proof" => Keyword::Proof, + "public_inputs" => Keyword::PublicInputs, + "key_hash" => Keyword::KeyHash, + "proof_type" => Keyword::ProofType, + "hash_values" => Keyword::HashValues, _ => return None, }; Some(Token::Keyword(keyword)) @@ -196,10 +250,28 @@ impl std::fmt::Display for Keyword { Keyword::ReturnData => write!(f, "RETURNDATA"), Keyword::Function => write!(f, "func"), Keyword::Input => write!(f, "input"), + Keyword::Input1 => write!(f, "input1"), + Keyword::Input2 => write!(f, "input2"), Keyword::Inputs => write!(f, "inputs"), Keyword::Output => write!(f, "output"), Keyword::Outputs => write!(f, "outputs"), Keyword::Bits => write!(f, "bits"), + Keyword::Iv => write!(f, "iv"), + Keyword::Key => write!(f, "key"), + Keyword::Lhs => write!(f, "lhs"), + Keyword::Rhs => write!(f, "rhs"), + Keyword::PublicKeyX => write!(f, "public_key_x"), + Keyword::PublicKeyY => write!(f, "public_key_y"), + Keyword::Signature => write!(f, "signature"), + Keyword::HashedMessage => write!(f, "hashed_message"), + Keyword::Points => write!(f, "points"), + Keyword::Scalars => write!(f, "scalars"), + Keyword::VerificationKey => write!(f, "verification_key"), + Keyword::Proof => write!(f, "proof"), + Keyword::PublicInputs => write!(f, "public_inputs"), + Keyword::KeyHash => write!(f, "key_hash"), + Keyword::ProofType => write!(f, "proof_type"), + Keyword::HashValues => write!(f, "hash_values"), } } } diff --git a/acvm-repo/acvm/src/compiler/optimizers/merge_expressions.rs b/acvm-repo/acvm/src/compiler/optimizers/merge_expressions.rs index 158f9a7451d..27ee46448d0 100644 --- a/acvm-repo/acvm/src/compiler/optimizers/merge_expressions.rs +++ b/acvm-repo/acvm/src/compiler/optimizers/merge_expressions.rs @@ -396,7 +396,7 @@ mod tests { public parameters: [] return values: [w2] BRILLIG CALL func: 0, inputs: [], outputs: [w3] - BLACKBOX::AND inputs: [w0, w1], bits: 8, output: w4 + BLACKBOX::AND lhs: w0, rhs: w1, output: w4, bits: 8 ASSERT w3 - w4 = 0 ASSERT -w2 + w4 = 0 "; diff --git a/compiler/noirc_evaluator/src/acir/acir_context/black_box.rs b/compiler/noirc_evaluator/src/acir/acir_context/black_box.rs index 5040d0f1d87..fe04e08e0b5 100644 --- a/compiler/noirc_evaluator/src/acir/acir_context/black_box.rs +++ b/compiler/noirc_evaluator/src/acir/acir_context/black_box.rs @@ -72,7 +72,7 @@ impl AcirContext { self.var_to_witness(*var).expect("variable was just created as witness") }); - self.acir_ir.call_black_box(name, &inputs, constant_inputs, num_bits, output_witnesses)?; + self.acir_ir.call_black_box(name, inputs, constant_inputs, num_bits, output_witnesses)?; // Convert `Witness` values which are now constrained to be the output of the // black box function call into `AcirVar`s. diff --git a/compiler/noirc_evaluator/src/acir/acir_context/generated_acir/mod.rs b/compiler/noirc_evaluator/src/acir/acir_context/generated_acir/mod.rs index 30d3384a52a..8b266b3d184 100644 --- a/compiler/noirc_evaluator/src/acir/acir_context/generated_acir/mod.rs +++ b/compiler/noirc_evaluator/src/acir/acir_context/generated_acir/mod.rs @@ -176,163 +176,152 @@ impl GeneratedAcir { pub(crate) fn call_black_box( &mut self, func_name: BlackBoxFunc, - function_inputs: &[Vec>], + function_inputs: Vec>>, constant_inputs: Vec, num_bits: Option, outputs: Vec, ) -> Result<(), InternalError> { + fn expect_into(value: T) -> U + where + T: TryInto, + >::Error: std::fmt::Debug, + { + value.try_into().expect("Compiler should generate correct size inputs/outputs") + } + let input_count = function_inputs.iter().fold(0usize, |sum, val| sum + val.len()); intrinsics_check_inputs(func_name, input_count); intrinsics_check_outputs(func_name, outputs.len()); let black_box_func_call = match func_name { - BlackBoxFunc::AES128Encrypt => BlackBoxFuncCall::AES128Encrypt { - inputs: function_inputs[0].clone(), - iv: function_inputs[1] - .clone() - .try_into() - .expect("Compiler should generate correct size inputs"), - key: function_inputs[2] - .clone() - .try_into() - .expect("Compiler should generate correct size inputs"), - outputs, - }, - BlackBoxFunc::AND => BlackBoxFuncCall::AND { - lhs: function_inputs[0][0], - rhs: function_inputs[1][0], - num_bits: num_bits.expect("missing num_bits"), - output: outputs[0], - }, - BlackBoxFunc::XOR => BlackBoxFuncCall::XOR { - lhs: function_inputs[0][0], - rhs: function_inputs[1][0], - num_bits: num_bits.expect("missing num_bits"), - output: outputs[0], - }, - BlackBoxFunc::RANGE => BlackBoxFuncCall::RANGE { - input: function_inputs[0][0], - num_bits: num_bits.expect("missing num_bits"), - }, - BlackBoxFunc::Blake2s => BlackBoxFuncCall::Blake2s { - inputs: function_inputs[0].clone(), - outputs: outputs.try_into().expect("Compiler should generate correct size outputs"), - }, - BlackBoxFunc::Blake3 => BlackBoxFuncCall::Blake3 { - inputs: function_inputs[0].clone(), - outputs: outputs.try_into().expect("Compiler should generate correct size outputs"), - }, + BlackBoxFunc::AES128Encrypt => { + let [inputs, iv, key] = expect_into(function_inputs); + let iv = expect_into(iv); + let key = expect_into(key); + BlackBoxFuncCall::AES128Encrypt { inputs, iv, key, outputs } + } + BlackBoxFunc::AND => { + let [lhs, rhs] = expect_into(function_inputs); + let num_bits = num_bits.expect("missing num_bits"); + BlackBoxFuncCall::AND { lhs: lhs[0], rhs: rhs[0], num_bits, output: outputs[0] } + } + BlackBoxFunc::XOR => { + let [lhs, rhs] = expect_into(function_inputs); + let num_bits = num_bits.expect("missing num_bits"); + BlackBoxFuncCall::XOR { lhs: lhs[0], rhs: rhs[0], num_bits, output: outputs[0] } + } + BlackBoxFunc::RANGE => { + let [input] = expect_into(function_inputs); + let num_bits = num_bits.expect("missing num_bits"); + BlackBoxFuncCall::RANGE { input: input[0], num_bits } + } + BlackBoxFunc::Blake2s => { + let [inputs] = expect_into(function_inputs); + let outputs = expect_into(outputs); + BlackBoxFuncCall::Blake2s { inputs: inputs.clone(), outputs } + } + BlackBoxFunc::Blake3 => { + let [inputs] = expect_into(function_inputs); + let outputs = expect_into(outputs); + BlackBoxFuncCall::Blake3 { inputs: inputs.clone(), outputs } + } BlackBoxFunc::EcdsaSecp256k1 => { - if function_inputs[0].len() != 32 - || function_inputs[1].len() != 32 - || function_inputs[2].len() != 64 - || function_inputs[3].len() != 32 - { - return Err(InternalError::General { - message: "Compiler should generate correct size inputs".to_string(), - call_stack: self.get_call_stack(), - }); - } + let [public_key_x, public_key_y, signature, hashed_message, predicate] = + expect_into(function_inputs); + let [predicate] = expect_into(predicate); + let [output] = expect_into(outputs); BlackBoxFuncCall::EcdsaSecp256k1 { // 32 bytes for each public key co-ordinate - public_key_x: function_inputs[0] - .clone() - .try_into() - .expect("Compiler should generate correct size inputs"), - public_key_y: function_inputs[1] - .clone() - .try_into() - .expect("Compiler should generate correct size inputs"), + public_key_x: expect_into(public_key_x), + public_key_y: expect_into(public_key_y), // (r,s) are both 32 bytes each, so signature // takes up 64 bytes - signature: function_inputs[2] - .clone() - .try_into() - .expect("Compiler should generate correct size inputs"), - hashed_message: function_inputs[3] - .clone() - .try_into() - .expect("Compiler should generate correct size inputs"), - predicate: function_inputs[4].clone()[0], - output: outputs[0], + signature: expect_into(signature), + hashed_message: expect_into(hashed_message), + predicate, + output, } } BlackBoxFunc::EcdsaSecp256r1 => { + let [public_key_x, public_key_y, signature, hashed_message, predicate] = + expect_into(function_inputs); + let [predicate] = expect_into(predicate); + let [output] = expect_into(outputs); BlackBoxFuncCall::EcdsaSecp256r1 { // 32 bytes for each public key co-ordinate - public_key_x: function_inputs[0] - .clone() - .try_into() - .expect("Compiler should generate correct size inputs"), - public_key_y: function_inputs[1] - .clone() - .clone() - .try_into() - .expect("Compiler should generate correct size inputs"), + public_key_x: expect_into(public_key_x), + public_key_y: expect_into(public_key_y), // (r,s) are both 32 bytes each, so signature // takes up 64 bytes - signature: function_inputs[2] - .clone() - .try_into() - .expect("Compiler should generate correct size inputs"), - hashed_message: function_inputs[3] - .clone() - .try_into() - .expect("Compiler should generate correct size inputs"), - predicate: function_inputs[4].clone()[0], - output: outputs[0], + signature: expect_into(signature), + hashed_message: expect_into(hashed_message), + predicate, + output, + } + } + BlackBoxFunc::MultiScalarMul => { + let [points, scalars, predicate] = expect_into(function_inputs); + let [predicate] = expect_into(predicate); + let [output0, output1, output2] = expect_into(outputs); + BlackBoxFuncCall::MultiScalarMul { + points, + scalars, + predicate, + outputs: (output0, output1, output2), + } + } + + BlackBoxFunc::EmbeddedCurveAdd => { + let [input1_0, input1_1, input1_2, input2_0, input2_1, input2_2, predicate] = + expect_into(function_inputs); + let [input1_0] = expect_into(input1_0); + let [input1_1] = expect_into(input1_1); + let [input1_2] = expect_into(input1_2); + let [input2_0] = expect_into(input2_0); + let [input2_1] = expect_into(input2_1); + let [input2_2] = expect_into(input2_2); + let [predicate] = expect_into(predicate); + let [output0, output1, output2] = expect_into(outputs); + BlackBoxFuncCall::EmbeddedCurveAdd { + input1: Box::new([input1_0, input1_1, input1_2]), + input2: Box::new([input2_0, input2_1, input2_2]), + predicate, + outputs: (output0, output1, output2), + } + } + BlackBoxFunc::Keccakf1600 => { + let [inputs] = expect_into(function_inputs); + BlackBoxFuncCall::Keccakf1600 { + inputs: expect_into(inputs), + outputs: expect_into(outputs), + } + } + BlackBoxFunc::RecursiveAggregation => { + let [verification_key, proof, public_inputs, key_hash, predicate] = + expect_into(function_inputs); + let [key_hash] = expect_into(key_hash); + let [proof_type] = expect_into(constant_inputs); + let [predicate] = expect_into(predicate); + BlackBoxFuncCall::RecursiveAggregation { + verification_key, + proof, + public_inputs, + key_hash, + proof_type: proof_type.to_u128() as u32, + predicate, + } + } + BlackBoxFunc::Poseidon2Permutation => { + let [inputs] = expect_into(function_inputs); + BlackBoxFuncCall::Poseidon2Permutation { inputs, outputs } + } + BlackBoxFunc::Sha256Compression => { + let [inputs, hash_values] = expect_into(function_inputs); + BlackBoxFuncCall::Sha256Compression { + inputs: expect_into(inputs), + hash_values: expect_into(hash_values), + outputs: expect_into(outputs), } } - BlackBoxFunc::MultiScalarMul => BlackBoxFuncCall::MultiScalarMul { - points: function_inputs[0].clone(), - scalars: function_inputs[1].clone(), - predicate: function_inputs[2].clone()[0], - outputs: (outputs[0], outputs[1], outputs[2]), - }, - - BlackBoxFunc::EmbeddedCurveAdd => BlackBoxFuncCall::EmbeddedCurveAdd { - input1: Box::new([ - function_inputs[0].clone()[0], - function_inputs[1].clone()[0], - function_inputs[2].clone()[0], - ]), - input2: Box::new([ - function_inputs[3].clone()[0], - function_inputs[4].clone()[0], - function_inputs[5].clone()[0], - ]), - predicate: function_inputs[6].clone()[0], - outputs: (outputs[0], outputs[1], outputs[2]), - }, - BlackBoxFunc::Keccakf1600 => BlackBoxFuncCall::Keccakf1600 { - inputs: function_inputs[0] - .clone() - .try_into() - .expect("Compiler should generate correct size inputs"), - outputs: outputs.try_into().expect("Compiler should generate correct size outputs"), - }, - BlackBoxFunc::RecursiveAggregation => BlackBoxFuncCall::RecursiveAggregation { - verification_key: function_inputs[0].clone(), - proof: function_inputs[1].clone(), - public_inputs: function_inputs[2].clone(), - key_hash: function_inputs[3].clone()[0], - proof_type: constant_inputs[0].to_u128() as u32, - predicate: function_inputs[4].clone()[0], - }, - BlackBoxFunc::Poseidon2Permutation => BlackBoxFuncCall::Poseidon2Permutation { - inputs: function_inputs[0].clone(), - outputs, - }, - BlackBoxFunc::Sha256Compression => BlackBoxFuncCall::Sha256Compression { - inputs: function_inputs[0] - .clone() - .try_into() - .expect("Compiler should generate correct size inputs"), - hash_values: function_inputs[1] - .clone() - .try_into() - .expect("Compiler should generate correct size inputs"), - outputs: outputs.try_into().expect("Compiler should generate correct size outputs"), - }, }; self.push_opcode(AcirOpcode::BlackBoxFuncCall(black_box_func_call)); diff --git a/compiler/noirc_evaluator/src/acir/tests/instructions/binary.rs b/compiler/noirc_evaluator/src/acir/tests/instructions/binary.rs index bd315442578..801343ed0f2 100644 --- a/compiler/noirc_evaluator/src/acir/tests/instructions/binary.rs +++ b/compiler/noirc_evaluator/src/acir/tests/instructions/binary.rs @@ -573,7 +573,7 @@ fn and_u8() { return values: [w2] BLACKBOX::RANGE input: w0, bits: 8 BLACKBOX::RANGE input: w1, bits: 8 - BLACKBOX::AND inputs: [w0, w1], bits: 8, output: w3 + BLACKBOX::AND lhs: w0, rhs: w1, output: w3, bits: 8 ASSERT w2 = w3 "); } @@ -624,7 +624,7 @@ fn or_u8() { BLACKBOX::RANGE input: w1, bits: 8 ASSERT w3 = -w0 + 255 ASSERT w4 = -w1 + 255 - BLACKBOX::AND inputs: [w3, w4], bits: 8, output: w5 + BLACKBOX::AND lhs: w3, rhs: w4, output: w5, bits: 8 ASSERT w2 = -w5 + 255 "); } @@ -672,7 +672,7 @@ fn xor_u8() { return values: [w2] BLACKBOX::RANGE input: w0, bits: 8 BLACKBOX::RANGE input: w1, bits: 8 - BLACKBOX::XOR inputs: [w0, w1], bits: 8, output: w3 + BLACKBOX::XOR lhs: w0, rhs: w1, output: w3, bits: 8 ASSERT w2 = w3 "); }