Skip to content
This repository has been archived by the owner on Apr 9, 2024. It is now read-only.

feat!: Add variable length keccak opcode #314

Merged
merged 10 commits into from
May 26, 2023
12 changes: 12 additions & 0 deletions acir/src/circuit/opcodes/black_box_function_call.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,11 @@ pub enum BlackBoxFuncCall {
inputs: Vec<FunctionInput>,
outputs: Vec<Witness>,
},
Keccak256VariableLength {
inputs: Vec<FunctionInput>,
var_message_size: FunctionInput,
kevaundray marked this conversation as resolved.
Show resolved Hide resolved
outputs: Vec<Witness>,
},
}

impl BlackBoxFuncCall {
Expand Down Expand Up @@ -132,6 +137,7 @@ impl BlackBoxFuncCall {
BlackBoxFuncCall::EcdsaSecp256k1 { .. } => BlackBoxFunc::EcdsaSecp256k1,
BlackBoxFuncCall::FixedBaseScalarMul { .. } => BlackBoxFunc::FixedBaseScalarMul,
BlackBoxFuncCall::Keccak256 { .. } => BlackBoxFunc::Keccak256,
BlackBoxFuncCall::Keccak256VariableLength { .. } => BlackBoxFunc::Keccak256,
}
}

Expand Down Expand Up @@ -184,6 +190,11 @@ impl BlackBoxFuncCall {
inputs.extend(hashed_message.iter().copied());
inputs
}
BlackBoxFuncCall::Keccak256VariableLength { inputs, var_message_size, .. } => {
let mut inputs = inputs.clone();
inputs.push(*var_message_size);
inputs
}
}
}

Expand All @@ -200,6 +211,7 @@ impl BlackBoxFuncCall {
| BlackBoxFuncCall::SchnorrVerify { output, .. }
| BlackBoxFuncCall::EcdsaSecp256k1 { output, .. } => vec![*output],
BlackBoxFuncCall::RANGE { .. } => vec![],
BlackBoxFuncCall::Keccak256VariableLength { outputs, .. } => outputs.to_vec(),
}
}
}
Expand Down
9 changes: 5 additions & 4 deletions acvm/src/pwg/blackbox.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use acir::{
};

use super::{
hash::{blake2s256, hash_to_field_128_security, keccak256, sha256},
hash::{blake2s256, hash_to_field_128_security, keccak256, keccak256_variable_length, sha256},
logic::{and, xor},
range::solve_range_opcode,
signature::ecdsa::secp256k1_prehashed,
Expand Down Expand Up @@ -49,9 +49,7 @@ pub(crate) fn solve(
}

match bb_func {
acir::circuit::opcodes::BlackBoxFuncCall::AND { lhs, rhs, output } => {
and(initial_witness, lhs, rhs, output)
}
BlackBoxFuncCall::AND { lhs, rhs, output } => and(initial_witness, lhs, rhs, output),
BlackBoxFuncCall::XOR { lhs, rhs, output } => xor(initial_witness, lhs, rhs, output),
BlackBoxFuncCall::RANGE { input } => solve_range_opcode(initial_witness, input),
BlackBoxFuncCall::SHA256 { inputs, outputs } => sha256(initial_witness, inputs, outputs),
Expand Down Expand Up @@ -98,5 +96,8 @@ pub(crate) fn solve(
BlackBoxFuncCall::Keccak256 { inputs, outputs } => {
keccak256(initial_witness, inputs, outputs)
}
BlackBoxFuncCall::Keccak256VariableLength { inputs, var_message_size, outputs } => {
keccak256_variable_length(initial_witness, inputs, *var_message_size, outputs)
}
}
}
44 changes: 39 additions & 5 deletions acvm/src/pwg/hash.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ pub fn blake2s256(
inputs: &[FunctionInput],
outputs: &[Witness],
) -> Result<OpcodeResolution, OpcodeResolutionError> {
let hash = generic_hash_256::<Blake2s256>(initial_witness, inputs)?;
let hash = generic_hash_256::<Blake2s256>(initial_witness, None, inputs)?;

for (output_witness, value) in outputs.iter().zip(hash.iter()) {
insert_value(
Expand All @@ -34,7 +34,7 @@ pub fn sha256(
inputs: &[FunctionInput],
outputs: &[Witness],
) -> Result<OpcodeResolution, OpcodeResolutionError> {
let hash = generic_hash_256::<Sha256>(initial_witness, inputs)?;
let hash = generic_hash_256::<Sha256>(initial_witness, None, inputs)?;

for (output_witness, value) in outputs.iter().zip(hash.iter()) {
insert_value(
Expand All @@ -52,7 +52,26 @@ pub fn keccak256(
inputs: &[FunctionInput],
outputs: &[Witness],
) -> Result<OpcodeResolution, OpcodeResolutionError> {
let hash = generic_hash_256::<Keccak256>(initial_witness, inputs)?;
let hash = generic_hash_256::<Keccak256>(initial_witness, None, inputs)?;

for (output_witness, value) in outputs.iter().zip(hash.iter()) {
insert_value(
output_witness,
FieldElement::from_be_bytes_reduce(&[*value]),
initial_witness,
)?;
}

Ok(OpcodeResolution::Solved)
}

pub fn keccak256_variable_length(
initial_witness: &mut WitnessMap,
inputs: &[FunctionInput],
var_message_size: FunctionInput,
outputs: &[Witness],
) -> Result<OpcodeResolution, OpcodeResolutionError> {
let hash = generic_hash_256::<Keccak256>(initial_witness, Some(var_message_size), inputs)?;

for (output_witness, value) in outputs.iter().zip(hash.iter()) {
insert_value(
Expand All @@ -70,7 +89,7 @@ pub fn hash_to_field_128_security(
inputs: &[FunctionInput],
output: &Witness,
) -> Result<OpcodeResolution, OpcodeResolutionError> {
let hash = generic_hash_256::<Blake2s256>(initial_witness, inputs)?;
let hash = generic_hash_256::<Blake2s256>(initial_witness, None, inputs)?;

let reduced_res = FieldElement::from_be_bytes_reduce(&hash);
insert_value(output, reduced_res, initial_witness)?;
Expand All @@ -80,18 +99,33 @@ pub fn hash_to_field_128_security(

fn generic_hash_256<D: Digest>(
initial_witness: &mut WitnessMap,
num_bytes_to_truncate_message: Option<FunctionInput>,
inputs: &[FunctionInput],
) -> Result<[u8; 32], OpcodeResolutionError> {
let mut hasher = D::new();

let mut message_input = Vec::new();

// Read witness assignments into hasher.
for input in inputs.iter() {
let witness = input.witness;
let num_bits = input.num_bits as usize;

let witness_assignment = witness_to_value(initial_witness, witness)?;
let bytes = witness_assignment.fetch_nearest_bytes(num_bits);
hasher.update(bytes);
message_input.extend(bytes);
}

// Truncate the message if there is a message_size parameter given
match num_bytes_to_truncate_message {
Some(input) => {
let num_bytes_to_take =
witness_to_value(initial_witness, input.witness)?.to_u128() as usize;

let truncated_message = &message_input[0..num_bytes_to_take];
hasher.update(truncated_message)
}
None => hasher.update(message_input),
}

let result = hasher.finalize().as_slice().try_into().unwrap();
Expand Down