From 4c0439ba901ef2479181ec4fae4275959136c45d Mon Sep 17 00:00:00 2001 From: sirasistant Date: Thu, 11 May 2023 15:25:24 +0000 Subject: [PATCH 1/4] feat: added hash index to pedersen --- .../opcodes/black_box_function_call.rs | 27 ++++++++++++++++--- acvm/src/lib.rs | 2 ++ acvm/src/pwg/blackbox.rs | 4 +-- 3 files changed, 27 insertions(+), 6 deletions(-) diff --git a/acir/src/circuit/opcodes/black_box_function_call.rs b/acir/src/circuit/opcodes/black_box_function_call.rs index d53486b07..8e1f90afa 100644 --- a/acir/src/circuit/opcodes/black_box_function_call.rs +++ b/acir/src/circuit/opcodes/black_box_function_call.rs @@ -62,6 +62,7 @@ pub enum BlackBoxFuncCall { }, Pedersen { inputs: Vec, + hash_index: u32, outputs: Vec, }, // 128 here specifies that this function @@ -179,7 +180,7 @@ impl BlackBoxFuncCall { output: Witness(0), }, BlackBoxFunc::Pedersen => { - BlackBoxFuncCall::Pedersen { inputs: vec![], outputs: vec![] } + BlackBoxFuncCall::Pedersen { inputs: vec![], hash_index: 0, outputs: vec![] } } BlackBoxFunc::HashToField128Security => { BlackBoxFuncCall::HashToField128Security { inputs: vec![], output: Witness(0) } @@ -300,7 +301,13 @@ impl BlackBoxFuncCall { write_inputs(&self.get_inputs_vec(), &mut writer)?; write_outputs(&self.get_outputs_vec(), &mut writer)?; - Ok(()) + match self { + BlackBoxFuncCall::Pedersen { hash_index, .. } => { + write_u32(&mut writer, *hash_index)?; + Ok(()) + } + _ => Ok(()), + } } pub fn read(mut reader: R) -> std::io::Result { @@ -366,7 +373,11 @@ impl BlackBoxFuncCall { }) } } - BlackBoxFunc::Pedersen => Ok(BlackBoxFuncCall::Pedersen { inputs, outputs }), + BlackBoxFunc::Pedersen => Ok(BlackBoxFuncCall::Pedersen { + inputs, + hash_index: read_u32(&mut reader)?, + outputs, + }), BlackBoxFunc::HashToField128Security => { if outputs.len() != 1 { Err(std::io::ErrorKind::InvalidData.into()) @@ -477,7 +488,15 @@ impl std::fmt::Display for BlackBoxFuncCall { write!(f, "{outputs_str}")?; - write!(f, "]") + write!(f, "]")?; + + // SPECIFIC PARAMETERS + match self { + BlackBoxFuncCall::Pedersen { hash_index, .. } => { + write!(f, " hash_index: {hash_index}") + } + _ => write!(f, ""), + } } } diff --git a/acvm/src/lib.rs b/acvm/src/lib.rs index 24a00dcc9..3dc75b467 100644 --- a/acvm/src/lib.rs +++ b/acvm/src/lib.rs @@ -120,6 +120,7 @@ pub trait PartialWitnessGenerator { &self, initial_witness: &mut BTreeMap, inputs: &[FunctionInput], + hash_index: u32, outputs: &[Witness], ) -> Result; fn hash_to_field_128_security( @@ -358,6 +359,7 @@ mod test { &self, _initial_witness: &mut BTreeMap, _inputs: &[FunctionInput], + _hash_index: u32, _outputs: &[Witness], ) -> Result { panic!("Path not trodden by this test") diff --git a/acvm/src/pwg/blackbox.rs b/acvm/src/pwg/blackbox.rs index 9b17e5305..e974eb0fc 100644 --- a/acvm/src/pwg/blackbox.rs +++ b/acvm/src/pwg/blackbox.rs @@ -83,8 +83,8 @@ pub(crate) fn solve( message, output, ), - BlackBoxFuncCall::Pedersen { inputs, outputs } => { - backend.pedersen(initial_witness, inputs, outputs) + BlackBoxFuncCall::Pedersen { inputs, hash_index, outputs } => { + backend.pedersen(initial_witness, inputs, *hash_index, outputs) } BlackBoxFuncCall::HashToField128Security { inputs, output } => { backend.hash_to_field_128_security(initial_witness, inputs, output) From 32297af6b8972089bc1f278a07512b985602e11d Mon Sep 17 00:00:00 2001 From: sirasistant Date: Fri, 12 May 2023 08:03:17 +0000 Subject: [PATCH 2/4] refactor: rename hash_index to domain separator --- .../src/circuit/opcodes/black_box_function_call.rs | 14 +++++++------- acvm/src/lib.rs | 4 ++-- acvm/src/pwg/blackbox.rs | 4 ++-- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/acir/src/circuit/opcodes/black_box_function_call.rs b/acir/src/circuit/opcodes/black_box_function_call.rs index 8e1f90afa..82c177128 100644 --- a/acir/src/circuit/opcodes/black_box_function_call.rs +++ b/acir/src/circuit/opcodes/black_box_function_call.rs @@ -62,7 +62,7 @@ pub enum BlackBoxFuncCall { }, Pedersen { inputs: Vec, - hash_index: u32, + domain_separator: u32, outputs: Vec, }, // 128 here specifies that this function @@ -180,7 +180,7 @@ impl BlackBoxFuncCall { output: Witness(0), }, BlackBoxFunc::Pedersen => { - BlackBoxFuncCall::Pedersen { inputs: vec![], hash_index: 0, outputs: vec![] } + BlackBoxFuncCall::Pedersen { inputs: vec![], domain_separator: 0, outputs: vec![] } } BlackBoxFunc::HashToField128Security => { BlackBoxFuncCall::HashToField128Security { inputs: vec![], output: Witness(0) } @@ -302,8 +302,8 @@ impl BlackBoxFuncCall { write_outputs(&self.get_outputs_vec(), &mut writer)?; match self { - BlackBoxFuncCall::Pedersen { hash_index, .. } => { - write_u32(&mut writer, *hash_index)?; + BlackBoxFuncCall::Pedersen { domain_separator, .. } => { + write_u32(&mut writer, *domain_separator)?; Ok(()) } _ => Ok(()), @@ -375,7 +375,7 @@ impl BlackBoxFuncCall { } BlackBoxFunc::Pedersen => Ok(BlackBoxFuncCall::Pedersen { inputs, - hash_index: read_u32(&mut reader)?, + domain_separator: read_u32(&mut reader)?, outputs, }), BlackBoxFunc::HashToField128Security => { @@ -492,8 +492,8 @@ impl std::fmt::Display for BlackBoxFuncCall { // SPECIFIC PARAMETERS match self { - BlackBoxFuncCall::Pedersen { hash_index, .. } => { - write!(f, " hash_index: {hash_index}") + BlackBoxFuncCall::Pedersen { domain_separator, .. } => { + write!(f, " domain_separator: {domain_separator}") } _ => write!(f, ""), } diff --git a/acvm/src/lib.rs b/acvm/src/lib.rs index 3dc75b467..547068a85 100644 --- a/acvm/src/lib.rs +++ b/acvm/src/lib.rs @@ -120,7 +120,7 @@ pub trait PartialWitnessGenerator { &self, initial_witness: &mut BTreeMap, inputs: &[FunctionInput], - hash_index: u32, + domain_separator: u32, outputs: &[Witness], ) -> Result; fn hash_to_field_128_security( @@ -359,7 +359,7 @@ mod test { &self, _initial_witness: &mut BTreeMap, _inputs: &[FunctionInput], - _hash_index: u32, + _domain_separator: u32, _outputs: &[Witness], ) -> Result { panic!("Path not trodden by this test") diff --git a/acvm/src/pwg/blackbox.rs b/acvm/src/pwg/blackbox.rs index e974eb0fc..748989e01 100644 --- a/acvm/src/pwg/blackbox.rs +++ b/acvm/src/pwg/blackbox.rs @@ -83,8 +83,8 @@ pub(crate) fn solve( message, output, ), - BlackBoxFuncCall::Pedersen { inputs, hash_index, outputs } => { - backend.pedersen(initial_witness, inputs, *hash_index, outputs) + BlackBoxFuncCall::Pedersen { inputs, domain_separator, outputs } => { + backend.pedersen(initial_witness, inputs, *domain_separator, outputs) } BlackBoxFuncCall::HashToField128Security { inputs, output } => { backend.hash_to_field_128_security(initial_witness, inputs, output) From 2e2865f8f2ba7305fbbf33616c62610a0509dbf5 Mon Sep 17 00:00:00 2001 From: sirasistant Date: Mon, 15 May 2023 07:55:28 +0000 Subject: [PATCH 3/4] refactor: extract bbcall read to separate fns --- .../opcodes/black_box_function_call.rs | 241 +++++++++++------- 1 file changed, 150 insertions(+), 91 deletions(-) diff --git a/acir/src/circuit/opcodes/black_box_function_call.rs b/acir/src/circuit/opcodes/black_box_function_call.rs index 82c177128..71607af8a 100644 --- a/acir/src/circuit/opcodes/black_box_function_call.rs +++ b/acir/src/circuit/opcodes/black_box_function_call.rs @@ -149,6 +149,143 @@ fn read_outputs(mut reader: R) -> std::io::Result> { Ok(outputs) } +fn read_aes(mut reader: R) -> std::io::Result { + let inputs = read_inputs(&mut reader)?; + let outputs = read_outputs(&mut reader)?; + Ok(BlackBoxFuncCall::AES { inputs, outputs }) +} + +fn read_and(mut reader: R) -> std::io::Result { + let inputs = read_inputs(&mut reader)?; + let outputs = read_outputs(&mut reader)?; + if inputs.len() != 2 || outputs.len() != 1 { + Err(std::io::ErrorKind::InvalidData.into()) + } else { + let lhs = inputs[0]; + let rhs = inputs[1]; + let output = outputs[0]; + Ok(BlackBoxFuncCall::AND { lhs, rhs, output }) + } +} + +fn read_xor(mut reader: R) -> std::io::Result { + let inputs = read_inputs(&mut reader)?; + let outputs = read_outputs(&mut reader)?; + if inputs.len() != 2 || outputs.len() != 1 { + Err(std::io::ErrorKind::InvalidData.into()) + } else { + let lhs = inputs[0]; + let rhs = inputs[1]; + let output = outputs[0]; + Ok(BlackBoxFuncCall::XOR { lhs, rhs, output }) + } +} + +fn read_range(mut reader: R) -> std::io::Result { + let inputs = read_inputs(&mut reader)?; + read_outputs(&mut reader)?; + if inputs.len() != 1 { + Err(std::io::ErrorKind::InvalidData.into()) + } else { + Ok(BlackBoxFuncCall::RANGE { input: inputs[0] }) + } +} + +fn read_sha256(mut reader: R) -> std::io::Result { + let inputs = read_inputs(&mut reader)?; + let outputs = read_outputs(&mut reader)?; + Ok(BlackBoxFuncCall::SHA256 { inputs, outputs }) +} + +fn read_blake2s(mut reader: R) -> std::io::Result { + let inputs = read_inputs(&mut reader)?; + let outputs = read_outputs(&mut reader)?; + Ok(BlackBoxFuncCall::Blake2s { inputs, outputs }) +} + +fn read_compute_merkle_root(mut reader: R) -> std::io::Result { + let inputs = read_inputs(&mut reader)?; + let outputs = read_outputs(&mut reader)?; + if inputs.len() < 2 || outputs.len() != 1 { + Err(std::io::ErrorKind::InvalidData.into()) + } else { + Ok(BlackBoxFuncCall::ComputeMerkleRoot { + leaf: inputs[0], + index: inputs[1], + hash_path: inputs[2..].to_vec(), + output: outputs[0], + }) + } +} + +fn read_schnorr(mut reader: R) -> std::io::Result { + let inputs = read_inputs(&mut reader)?; + let outputs = read_outputs(&mut reader)?; + if inputs.len() < 66 || outputs.len() != 1 { + Err(std::io::ErrorKind::InvalidData.into()) + } else { + Ok(BlackBoxFuncCall::SchnorrVerify { + public_key_x: inputs[0], + public_key_y: inputs[1], + signature: inputs[2..66].to_vec(), + message: inputs[66..].to_vec(), + output: outputs[0], + }) + } +} + +fn read_pedersen(mut reader: R) -> std::io::Result { + let inputs = read_inputs(&mut reader)?; + let outputs = read_outputs(&mut reader)?; + let domain_separator = read_u32(&mut reader)?; + + Ok(BlackBoxFuncCall::Pedersen { inputs, domain_separator, outputs }) +} + +fn read_hash_to_field(mut reader: R) -> std::io::Result { + let inputs = read_inputs(&mut reader)?; + let outputs = read_outputs(&mut reader)?; + + if outputs.len() != 1 { + Err(std::io::ErrorKind::InvalidData.into()) + } else { + Ok(BlackBoxFuncCall::HashToField128Security { inputs, output: outputs[0] }) + } +} + +fn read_ecdsa_secp256k1(mut reader: R) -> std::io::Result { + let inputs = read_inputs(&mut reader)?; + let outputs = read_outputs(&mut reader)?; + + if inputs.len() < 128 || outputs.len() != 1 { + Err(std::io::ErrorKind::InvalidData.into()) + } else { + Ok(BlackBoxFuncCall::EcdsaSecp256k1 { + public_key_x: inputs[0..32].to_vec(), + public_key_y: inputs[32..64].to_vec(), + signature: inputs[64..128].to_vec(), + hashed_message: inputs[128..].to_vec(), + output: outputs[0], + }) + } +} + +fn read_fixed_base_scalar_mul(mut reader: R) -> std::io::Result { + let inputs = read_inputs(&mut reader)?; + let outputs = read_outputs(&mut reader)?; + if inputs.len() != 1 { + Err(std::io::ErrorKind::InvalidData.into()) + } else { + Ok(BlackBoxFuncCall::FixedBaseScalarMul { input: inputs[0], outputs }) + } +} + +fn read_keccak256(mut reader: R) -> std::io::Result { + let inputs = read_inputs(&mut reader)?; + let outputs = read_outputs(&mut reader)?; + Ok(BlackBoxFuncCall::Keccak256 { inputs, outputs }) +} + impl BlackBoxFuncCall { pub fn dummy(bb_func: BlackBoxFunc) -> Self { match bb_func { @@ -314,98 +451,20 @@ impl BlackBoxFuncCall { let func_index = read_u16(&mut reader)?; let name = BlackBoxFunc::from_u16(func_index).ok_or(std::io::ErrorKind::InvalidData)?; - let inputs = read_inputs(&mut reader)?; - let outputs = read_outputs(&mut reader)?; - match name { - BlackBoxFunc::AES => Ok(BlackBoxFuncCall::AES { inputs, outputs }), - BlackBoxFunc::AND => { - if inputs.len() != 2 || outputs.len() != 1 { - Err(std::io::ErrorKind::InvalidData.into()) - } else { - let lhs = inputs[0]; - let rhs = inputs[1]; - let output = outputs[0]; - Ok(BlackBoxFuncCall::AND { lhs, rhs, output }) - } - } - BlackBoxFunc::XOR => { - if inputs.len() != 2 || outputs.len() != 1 { - Err(std::io::ErrorKind::InvalidData.into()) - } else { - let lhs = inputs[0]; - let rhs = inputs[1]; - let output = outputs[0]; - Ok(BlackBoxFuncCall::XOR { lhs, rhs, output }) - } - } - BlackBoxFunc::RANGE => { - if inputs.len() != 1 { - Err(std::io::ErrorKind::InvalidData.into()) - } else { - Ok(BlackBoxFuncCall::RANGE { input: inputs[0] }) - } - } - BlackBoxFunc::SHA256 => Ok(BlackBoxFuncCall::SHA256 { inputs, outputs }), - BlackBoxFunc::Blake2s => Ok(BlackBoxFuncCall::Blake2s { inputs, outputs }), - BlackBoxFunc::ComputeMerkleRoot => { - if inputs.len() < 2 || outputs.len() != 1 { - Err(std::io::ErrorKind::InvalidData.into()) - } else { - Ok(BlackBoxFuncCall::ComputeMerkleRoot { - leaf: inputs[0], - index: inputs[1], - hash_path: inputs[2..].to_vec(), - output: outputs[0], - }) - } - } - BlackBoxFunc::SchnorrVerify => { - if inputs.len() < 66 || outputs.len() != 1 { - Err(std::io::ErrorKind::InvalidData.into()) - } else { - Ok(BlackBoxFuncCall::SchnorrVerify { - public_key_x: inputs[0], - public_key_y: inputs[1], - signature: inputs[2..66].to_vec(), - message: inputs[66..].to_vec(), - output: outputs[0], - }) - } - } - BlackBoxFunc::Pedersen => Ok(BlackBoxFuncCall::Pedersen { - inputs, - domain_separator: read_u32(&mut reader)?, - outputs, - }), - BlackBoxFunc::HashToField128Security => { - if outputs.len() != 1 { - Err(std::io::ErrorKind::InvalidData.into()) - } else { - Ok(BlackBoxFuncCall::HashToField128Security { inputs, output: outputs[0] }) - } - } - BlackBoxFunc::EcdsaSecp256k1 => { - if inputs.len() < 128 || outputs.len() != 1 { - Err(std::io::ErrorKind::InvalidData.into()) - } else { - Ok(BlackBoxFuncCall::EcdsaSecp256k1 { - public_key_x: inputs[0..32].to_vec(), - public_key_y: inputs[32..64].to_vec(), - signature: inputs[64..128].to_vec(), - hashed_message: inputs[128..].to_vec(), - output: outputs[0], - }) - } - } - BlackBoxFunc::FixedBaseScalarMul => { - if inputs.len() != 1 { - Err(std::io::ErrorKind::InvalidData.into()) - } else { - Ok(BlackBoxFuncCall::FixedBaseScalarMul { input: inputs[0], outputs }) - } - } - BlackBoxFunc::Keccak256 => Ok(BlackBoxFuncCall::Keccak256 { inputs, outputs }), + BlackBoxFunc::AES => read_aes(&mut reader), + BlackBoxFunc::AND => read_and(&mut reader), + BlackBoxFunc::XOR => read_xor(&mut reader), + BlackBoxFunc::SHA256 => read_sha256(&mut reader), + BlackBoxFunc::Blake2s => read_blake2s(&mut reader), + BlackBoxFunc::FixedBaseScalarMul => read_fixed_base_scalar_mul(&mut reader), + BlackBoxFunc::Pedersen => read_pedersen(&mut reader), + BlackBoxFunc::Keccak256 => read_keccak256(&mut reader), + BlackBoxFunc::HashToField128Security => read_hash_to_field(&mut reader), + BlackBoxFunc::RANGE => read_range(&mut reader), + BlackBoxFunc::ComputeMerkleRoot => read_compute_merkle_root(&mut reader), + BlackBoxFunc::SchnorrVerify => read_schnorr(&mut reader), + BlackBoxFunc::EcdsaSecp256k1 => read_ecdsa_secp256k1(&mut reader), } } } From d946133c3194bfca7b97834fe3ec108cb049c85c Mon Sep 17 00:00:00 2001 From: sirasistant Date: Tue, 16 May 2023 19:31:35 +0000 Subject: [PATCH 4/4] feat: specific write fns per bb call --- .../opcodes/black_box_function_call.rs | 363 +++++++++++++----- 1 file changed, 260 insertions(+), 103 deletions(-) diff --git a/acir/src/circuit/opcodes/black_box_function_call.rs b/acir/src/circuit/opcodes/black_box_function_call.rs index 71607af8a..f1cc7b5b0 100644 --- a/acir/src/circuit/opcodes/black_box_function_call.rs +++ b/acir/src/circuit/opcodes/black_box_function_call.rs @@ -95,38 +95,38 @@ fn write_input(input: &FunctionInput, mut writer: W) -> std::io::Resul } fn write_inputs(inputs: &[FunctionInput], mut writer: W) -> std::io::Result<()> { - let num_inputs = inputs.len() as u32; - write_u32(&mut writer, num_inputs)?; - for input in inputs { write_input(input, &mut writer)?; } - Ok(()) } -fn write_outputs(outputs: &[Witness], mut writer: W) -> std::io::Result<()> { - let num_inputs = outputs.len() as u32; - write_u32(&mut writer, num_inputs)?; +fn write_variable_inputs(inputs: &[FunctionInput], mut writer: W) -> std::io::Result<()> { + write_u32(&mut writer, inputs.len() as u32)?; + write_inputs(inputs, &mut writer) +} +fn write_outputs(outputs: &[Witness], mut writer: W) -> std::io::Result<()> { for output in outputs { write_u32(&mut writer, output.witness_index())?; } - Ok(()) } +fn write_variable_outputs(outputs: &[Witness], mut writer: W) -> std::io::Result<()> { + write_u32(&mut writer, outputs.len() as u32)?; + write_outputs(outputs, &mut writer) +} + fn read_input(mut reader: R) -> std::io::Result { let witness_index = read_u32(&mut reader)?; let num_bits = read_u32(&mut reader)?; Ok(FunctionInput { witness: Witness::new(witness_index), num_bits }) } -fn read_inputs(mut reader: R) -> std::io::Result> { - let num_inputs = read_u32(&mut reader)?; - +fn read_inputs(mut reader: R, num_inputs: usize) -> std::io::Result> { let mut inputs = Vec::new(); - inputs.try_reserve_exact(num_inputs as usize).map_err(|_| std::io::ErrorKind::InvalidData)?; + inputs.try_reserve_exact(num_inputs).map_err(|_| std::io::ErrorKind::InvalidData)?; for _ in 0..num_inputs { inputs.push(read_input(&mut reader)?); @@ -135,11 +135,14 @@ fn read_inputs(mut reader: R) -> std::io::Result> { Ok(inputs) } -fn read_outputs(mut reader: R) -> std::io::Result> { - let num_outputs = read_u32(&mut reader)?; +fn read_variable_inputs(mut reader: R) -> std::io::Result> { + let num_inputs = read_u32(&mut reader)?; + read_inputs(&mut reader, num_inputs as usize) +} +fn read_outputs(mut reader: R, num_outputs: usize) -> std::io::Result> { let mut outputs = Vec::new(); - outputs.try_reserve_exact(num_outputs as usize).map_err(|_| std::io::ErrorKind::InvalidData)?; + outputs.try_reserve_exact(num_outputs).map_err(|_| std::io::ErrorKind::InvalidData)?; for _ in 0..num_outputs { let witness_index = read_u32(&mut reader)?; @@ -149,143 +152,286 @@ fn read_outputs(mut reader: R) -> std::io::Result> { Ok(outputs) } +fn read_variable_outputs(mut reader: R) -> std::io::Result> { + let num_outputs = read_u32(&mut reader)?; + read_outputs(&mut reader, num_outputs as usize) +} + fn read_aes(mut reader: R) -> std::io::Result { - let inputs = read_inputs(&mut reader)?; - let outputs = read_outputs(&mut reader)?; + let inputs = read_variable_inputs(&mut reader)?; + let outputs = read_variable_outputs(&mut reader)?; Ok(BlackBoxFuncCall::AES { inputs, outputs }) } +fn write_aes(func_call: &BlackBoxFuncCall, mut writer: W) -> std::io::Result<()> { + match func_call { + BlackBoxFuncCall::AES { inputs, outputs } => { + write_variable_inputs(inputs, &mut writer)?; + write_variable_outputs(outputs, &mut writer)?; + } + _ => return Err(std::io::ErrorKind::InvalidData.into()), + } + Ok(()) +} + fn read_and(mut reader: R) -> std::io::Result { - let inputs = read_inputs(&mut reader)?; - let outputs = read_outputs(&mut reader)?; - if inputs.len() != 2 || outputs.len() != 1 { - Err(std::io::ErrorKind::InvalidData.into()) - } else { - let lhs = inputs[0]; - let rhs = inputs[1]; - let output = outputs[0]; - Ok(BlackBoxFuncCall::AND { lhs, rhs, output }) + let lhs = read_input(&mut reader)?; + let rhs = read_input(&mut reader)?; + let output = Witness::new(read_u32(&mut reader)?); + + Ok(BlackBoxFuncCall::AND { lhs, rhs, output }) +} + +fn write_and(func_call: &BlackBoxFuncCall, mut writer: W) -> std::io::Result<()> { + match func_call { + BlackBoxFuncCall::AND { lhs, rhs, output } => { + write_input(lhs, &mut writer)?; + write_input(rhs, &mut writer)?; + write_u32(&mut writer, output.witness_index())?; + } + _ => return Err(std::io::ErrorKind::InvalidData.into()), } + Ok(()) } fn read_xor(mut reader: R) -> std::io::Result { - let inputs = read_inputs(&mut reader)?; - let outputs = read_outputs(&mut reader)?; - if inputs.len() != 2 || outputs.len() != 1 { - Err(std::io::ErrorKind::InvalidData.into()) - } else { - let lhs = inputs[0]; - let rhs = inputs[1]; - let output = outputs[0]; - Ok(BlackBoxFuncCall::XOR { lhs, rhs, output }) + let lhs = read_input(&mut reader)?; + let rhs = read_input(&mut reader)?; + let output = Witness::new(read_u32(&mut reader)?); + + Ok(BlackBoxFuncCall::XOR { lhs, rhs, output }) +} + +fn write_xor(func_call: &BlackBoxFuncCall, mut writer: W) -> std::io::Result<()> { + match func_call { + BlackBoxFuncCall::XOR { lhs, rhs, output } => { + write_input(lhs, &mut writer)?; + write_input(rhs, &mut writer)?; + write_u32(&mut writer, output.witness_index())?; + } + _ => return Err(std::io::ErrorKind::InvalidData.into()), } + Ok(()) } fn read_range(mut reader: R) -> std::io::Result { - let inputs = read_inputs(&mut reader)?; - read_outputs(&mut reader)?; - if inputs.len() != 1 { - Err(std::io::ErrorKind::InvalidData.into()) - } else { - Ok(BlackBoxFuncCall::RANGE { input: inputs[0] }) + let input = read_input(&mut reader)?; + Ok(BlackBoxFuncCall::RANGE { input }) +} + +fn write_range(func_call: &BlackBoxFuncCall, mut writer: W) -> std::io::Result<()> { + match func_call { + BlackBoxFuncCall::RANGE { input } => { + write_input(input, &mut writer)?; + } + _ => return Err(std::io::ErrorKind::InvalidData.into()), } + Ok(()) } fn read_sha256(mut reader: R) -> std::io::Result { - let inputs = read_inputs(&mut reader)?; - let outputs = read_outputs(&mut reader)?; + let inputs = read_variable_inputs(&mut reader)?; + let outputs = read_outputs(&mut reader, 32)?; Ok(BlackBoxFuncCall::SHA256 { inputs, outputs }) } +fn write_sha256(func_call: &BlackBoxFuncCall, mut writer: W) -> std::io::Result<()> { + match func_call { + BlackBoxFuncCall::SHA256 { inputs, outputs } => { + write_variable_inputs(inputs, &mut writer)?; + write_outputs(outputs, &mut writer)?; + } + _ => return Err(std::io::ErrorKind::InvalidData.into()), + } + Ok(()) +} + fn read_blake2s(mut reader: R) -> std::io::Result { - let inputs = read_inputs(&mut reader)?; - let outputs = read_outputs(&mut reader)?; + let inputs = read_variable_inputs(&mut reader)?; + let outputs = read_outputs(&mut reader, 32)?; Ok(BlackBoxFuncCall::Blake2s { inputs, outputs }) } +fn write_blake2s(func_call: &BlackBoxFuncCall, mut writer: W) -> std::io::Result<()> { + match func_call { + BlackBoxFuncCall::Blake2s { inputs, outputs } => { + write_variable_inputs(inputs, &mut writer)?; + write_outputs(outputs, &mut writer)?; + } + _ => return Err(std::io::ErrorKind::InvalidData.into()), + } + Ok(()) +} + fn read_compute_merkle_root(mut reader: R) -> std::io::Result { - let inputs = read_inputs(&mut reader)?; - let outputs = read_outputs(&mut reader)?; - if inputs.len() < 2 || outputs.len() != 1 { - Err(std::io::ErrorKind::InvalidData.into()) - } else { - Ok(BlackBoxFuncCall::ComputeMerkleRoot { - leaf: inputs[0], - index: inputs[1], - hash_path: inputs[2..].to_vec(), - output: outputs[0], - }) + let leaf = read_input(&mut reader)?; + let index = read_input(&mut reader)?; + let hash_path = read_variable_inputs(&mut reader)?; + let output = Witness::new(read_u32(&mut reader)?); + Ok(BlackBoxFuncCall::ComputeMerkleRoot { leaf, index, hash_path, output }) +} + +fn write_compute_merkle_root( + func_call: &BlackBoxFuncCall, + mut writer: W, +) -> std::io::Result<()> { + match func_call { + BlackBoxFuncCall::ComputeMerkleRoot { leaf, index, hash_path, output } => { + write_input(leaf, &mut writer)?; + write_input(index, &mut writer)?; + write_variable_inputs(hash_path, &mut writer)?; + write_u32(&mut writer, output.witness_index())?; + } + _ => return Err(std::io::ErrorKind::InvalidData.into()), } + Ok(()) } fn read_schnorr(mut reader: R) -> std::io::Result { - let inputs = read_inputs(&mut reader)?; - let outputs = read_outputs(&mut reader)?; - if inputs.len() < 66 || outputs.len() != 1 { - Err(std::io::ErrorKind::InvalidData.into()) - } else { - Ok(BlackBoxFuncCall::SchnorrVerify { - public_key_x: inputs[0], - public_key_y: inputs[1], - signature: inputs[2..66].to_vec(), - message: inputs[66..].to_vec(), - output: outputs[0], - }) + let public_key_x = read_input(&mut reader)?; + let public_key_y = read_input(&mut reader)?; + let signature = read_inputs(&mut reader, 64)?; + let message = read_variable_inputs(&mut reader)?; + let output = Witness::new(read_u32(&mut reader)?); + Ok(BlackBoxFuncCall::SchnorrVerify { public_key_x, public_key_y, signature, message, output }) +} + +fn write_schnorr(func_call: &BlackBoxFuncCall, mut writer: W) -> std::io::Result<()> { + match func_call { + BlackBoxFuncCall::SchnorrVerify { + public_key_x, + public_key_y, + signature, + message, + output, + } => { + write_input(public_key_x, &mut writer)?; + write_input(public_key_y, &mut writer)?; + write_inputs(signature, &mut writer)?; + write_variable_inputs(message, &mut writer)?; + write_u32(&mut writer, output.witness_index())?; + } + _ => return Err(std::io::ErrorKind::InvalidData.into()), } + Ok(()) } fn read_pedersen(mut reader: R) -> std::io::Result { - let inputs = read_inputs(&mut reader)?; - let outputs = read_outputs(&mut reader)?; + let inputs = read_variable_inputs(&mut reader)?; let domain_separator = read_u32(&mut reader)?; + let outputs = read_outputs(&mut reader, 2)?; Ok(BlackBoxFuncCall::Pedersen { inputs, domain_separator, outputs }) } +fn write_pedersen(func_call: &BlackBoxFuncCall, mut writer: W) -> std::io::Result<()> { + match func_call { + BlackBoxFuncCall::Pedersen { inputs, domain_separator, outputs } => { + write_variable_inputs(inputs, &mut writer)?; + write_u32(&mut writer, *domain_separator)?; + write_outputs(outputs, &mut writer)?; + } + _ => return Err(std::io::ErrorKind::InvalidData.into()), + } + Ok(()) +} + fn read_hash_to_field(mut reader: R) -> std::io::Result { - let inputs = read_inputs(&mut reader)?; - let outputs = read_outputs(&mut reader)?; + let inputs = read_variable_inputs(&mut reader)?; + let output = Witness::new(read_u32(&mut reader)?); - if outputs.len() != 1 { - Err(std::io::ErrorKind::InvalidData.into()) - } else { - Ok(BlackBoxFuncCall::HashToField128Security { inputs, output: outputs[0] }) + Ok(BlackBoxFuncCall::HashToField128Security { inputs, output }) +} + +fn write_hash_to_field( + func_call: &BlackBoxFuncCall, + mut writer: W, +) -> std::io::Result<()> { + match func_call { + BlackBoxFuncCall::HashToField128Security { inputs, output } => { + write_variable_inputs(inputs, &mut writer)?; + write_u32(&mut writer, output.witness_index())?; + } + _ => return Err(std::io::ErrorKind::InvalidData.into()), } + Ok(()) } fn read_ecdsa_secp256k1(mut reader: R) -> std::io::Result { - let inputs = read_inputs(&mut reader)?; - let outputs = read_outputs(&mut reader)?; + let public_key_x = read_inputs(&mut reader, 32)?; + let public_key_y = read_inputs(&mut reader, 32)?; + let signature = read_inputs(&mut reader, 64)?; + let hashed_message = read_variable_inputs(&mut reader)?; + let output = Witness::new(read_u32(&mut reader)?); + Ok(BlackBoxFuncCall::EcdsaSecp256k1 { + public_key_x, + public_key_y, + signature, + hashed_message, + output, + }) +} - if inputs.len() < 128 || outputs.len() != 1 { - Err(std::io::ErrorKind::InvalidData.into()) - } else { - Ok(BlackBoxFuncCall::EcdsaSecp256k1 { - public_key_x: inputs[0..32].to_vec(), - public_key_y: inputs[32..64].to_vec(), - signature: inputs[64..128].to_vec(), - hashed_message: inputs[128..].to_vec(), - output: outputs[0], - }) +fn write_ecdsa_secp256k1( + func_call: &BlackBoxFuncCall, + mut writer: W, +) -> std::io::Result<()> { + match func_call { + BlackBoxFuncCall::EcdsaSecp256k1 { + public_key_x, + public_key_y, + signature, + hashed_message, + output, + } => { + write_inputs(public_key_x, &mut writer)?; + write_inputs(public_key_y, &mut writer)?; + write_inputs(signature, &mut writer)?; + write_variable_inputs(hashed_message, &mut writer)?; + write_u32(&mut writer, output.witness_index())?; + } + _ => return Err(std::io::ErrorKind::InvalidData.into()), } + Ok(()) } fn read_fixed_base_scalar_mul(mut reader: R) -> std::io::Result { - let inputs = read_inputs(&mut reader)?; - let outputs = read_outputs(&mut reader)?; - if inputs.len() != 1 { - Err(std::io::ErrorKind::InvalidData.into()) - } else { - Ok(BlackBoxFuncCall::FixedBaseScalarMul { input: inputs[0], outputs }) + let input = read_input(&mut reader)?; + let outputs = read_outputs(&mut reader, 2)?; + Ok(BlackBoxFuncCall::FixedBaseScalarMul { input, outputs }) +} + +fn write_fixed_base_scalar_mul( + func_call: &BlackBoxFuncCall, + mut writer: W, +) -> std::io::Result<()> { + match func_call { + BlackBoxFuncCall::FixedBaseScalarMul { input, outputs } => { + write_input(input, &mut writer)?; + write_outputs(outputs, &mut writer)?; + } + _ => return Err(std::io::ErrorKind::InvalidData.into()), } + Ok(()) } fn read_keccak256(mut reader: R) -> std::io::Result { - let inputs = read_inputs(&mut reader)?; - let outputs = read_outputs(&mut reader)?; + let inputs = read_variable_inputs(&mut reader)?; + let outputs = read_outputs(&mut reader, 32)?; Ok(BlackBoxFuncCall::Keccak256 { inputs, outputs }) } +fn write_keccak256(func_call: &BlackBoxFuncCall, mut writer: W) -> std::io::Result<()> { + match func_call { + BlackBoxFuncCall::Keccak256 { inputs, outputs } => { + write_variable_inputs(inputs, &mut writer)?; + write_outputs(outputs, &mut writer)?; + } + _ => return Err(std::io::ErrorKind::InvalidData.into()), + } + Ok(()) +} + impl BlackBoxFuncCall { pub fn dummy(bb_func: BlackBoxFunc) -> Self { match bb_func { @@ -435,15 +581,26 @@ impl BlackBoxFuncCall { pub fn write(&self, mut writer: W) -> std::io::Result<()> { write_u16(&mut writer, self.get_black_box_func().to_u16())?; - write_inputs(&self.get_inputs_vec(), &mut writer)?; - write_outputs(&self.get_outputs_vec(), &mut writer)?; - match self { - BlackBoxFuncCall::Pedersen { domain_separator, .. } => { - write_u32(&mut writer, *domain_separator)?; - Ok(()) + BlackBoxFuncCall::AES { .. } => write_aes(self, &mut writer), + BlackBoxFuncCall::AND { .. } => write_and(self, &mut writer), + BlackBoxFuncCall::XOR { .. } => write_xor(self, &mut writer), + BlackBoxFuncCall::SHA256 { .. } => write_sha256(self, &mut writer), + BlackBoxFuncCall::Blake2s { .. } => write_blake2s(self, &mut writer), + BlackBoxFuncCall::FixedBaseScalarMul { .. } => { + write_fixed_base_scalar_mul(self, &mut writer) + } + BlackBoxFuncCall::Pedersen { .. } => write_pedersen(self, &mut writer), + BlackBoxFuncCall::Keccak256 { .. } => write_keccak256(self, &mut writer), + BlackBoxFuncCall::HashToField128Security { .. } => { + write_hash_to_field(self, &mut writer) + } + BlackBoxFuncCall::RANGE { .. } => write_range(self, &mut writer), + BlackBoxFuncCall::ComputeMerkleRoot { .. } => { + write_compute_merkle_root(self, &mut writer) } - _ => Ok(()), + BlackBoxFuncCall::SchnorrVerify { .. } => write_schnorr(self, &mut writer), + BlackBoxFuncCall::EcdsaSecp256k1 { .. } => write_ecdsa_secp256k1(self, &mut writer), } }