This repository has been archived by the owner on Apr 9, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 16
feat: Solve Keccak opcodes #247
Closed
Closed
Changes from all commits
Commits
Show all changes
4 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
use std::collections::BTreeMap; | ||
|
||
use acir::{circuit::opcodes::BlackBoxFuncCall, native_types::Witness, BlackBoxFunc, FieldElement}; | ||
|
||
use crate::{OpcodeNotSolvable, OpcodeResolution, OpcodeResolutionError}; | ||
|
||
use super::hash; | ||
|
||
pub fn solve_black_box_function( | ||
initial_witness: &mut BTreeMap<Witness, FieldElement>, | ||
func_call: &BlackBoxFuncCall, | ||
) -> Result<OpcodeResolution, OpcodeResolutionError> { | ||
match func_call.name { | ||
BlackBoxFunc::AES | ||
| BlackBoxFunc::AND | ||
| BlackBoxFunc::XOR | ||
| BlackBoxFunc::RANGE | ||
| BlackBoxFunc::SHA256 | ||
| BlackBoxFunc::Blake2s | ||
| BlackBoxFunc::ComputeMerkleRoot | ||
| BlackBoxFunc::SchnorrVerify | ||
| BlackBoxFunc::Pedersen | ||
| BlackBoxFunc::HashToField128Security | ||
| BlackBoxFunc::EcdsaSecp256k1 | ||
| BlackBoxFunc::FixedBaseScalarMul => { | ||
Err(OpcodeResolutionError::OpcodeNotSolvable(OpcodeNotSolvable::MissingAssignment(0))) | ||
} | ||
//self.solve_black_box_function_call(initial_witness, func_call), | ||
BlackBoxFunc::Keccak256 => { | ||
hash::keccak256(initial_witness, func_call)?; | ||
Ok(OpcodeResolution::Solved) | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,7 @@ | ||
use acir::{circuit::opcodes::BlackBoxFuncCall, native_types::Witness, FieldElement}; | ||
use blake2::{Blake2s, Digest}; | ||
use sha2::Sha256; | ||
use sha3::Keccak256; | ||
use std::collections::BTreeMap; | ||
|
||
use crate::{OpcodeResolution, OpcodeResolutionError}; | ||
|
@@ -72,3 +73,43 @@ fn generic_hash_256<D: Digest>( | |
let result = hasher.finalize().as_slice().try_into().unwrap(); | ||
Ok(result) | ||
} | ||
|
||
pub fn keccak256( | ||
initial_witness: &mut BTreeMap<Witness, FieldElement>, | ||
gadget_call: &BlackBoxFuncCall, | ||
) -> Result<OpcodeResolution, OpcodeResolutionError> { | ||
generic_sha3::<Keccak256>(initial_witness, gadget_call)?; | ||
Ok(OpcodeResolution::Solved) | ||
} | ||
|
||
fn generic_sha3<D: sha3::Digest>( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is the same There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It is not the same because the two crates do not use the same version. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Indeed, you'll need to adjust the dependency version for the blake2 crate to match. |
||
initial_witness: &mut BTreeMap<Witness, FieldElement>, | ||
gadget_call: &BlackBoxFuncCall, | ||
) -> Result<(), OpcodeResolutionError> { | ||
let mut hasher = D::new(); | ||
|
||
// For each input in the vector of inputs, check if we have their witness assignments (Can do this outside of match, since they all have inputs) | ||
for input_index in gadget_call.inputs.iter() { | ||
let witness = &input_index.witness; | ||
let num_bits = input_index.num_bits; | ||
|
||
let witness_assignment = initial_witness.get(witness); | ||
let assignment = match witness_assignment { | ||
None => panic!("cannot find witness assignment for {witness:?}"), | ||
Some(assignment) => assignment, | ||
}; | ||
|
||
let bytes = assignment.fetch_nearest_bytes(num_bits as usize); | ||
hasher.update(bytes); | ||
} | ||
let result = hasher.finalize(); | ||
assert_eq!(result.len(), 32); | ||
for i in 0..32 { | ||
insert_value( | ||
&gadget_call.outputs[i], | ||
FieldElement::from_be_bytes_reduce(&[result[i]]), | ||
initial_witness, | ||
)?; | ||
} | ||
Ok(()) | ||
} |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This change is unrelated to supporting keccak opcodes and has significant knock on effects for all backends so shouldn't be included in this PR.
This change is breaking.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think it is a breaking change, what is broken?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's changing the contract between backends and ACVM.
Previously ACVM provided reference methods for executing black box functions to the backends however backends were in charge of solving the black box function and returning the result. After this change this is still the case for all other opcodes but we'll never send keccak256 in particular to the backend.
This split between keccak256 and all the other functions doesn't make sense and we shouldn't split responsibility for black box function execution between the backend and the ACVM. Until we have a rust implementation of all black box functions then we should allow the backend to handle this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So in fact this is not breaking anything.
Solving Keccak in ACVM does make sense, as well as all other 'blackbox'. I will move the solving into ACVM for all but pedersen, which will still be handled by the backend until we have a rust implementation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This change would mean that a lot of code in aztec_backend would become dead code without us actually realizing it. The backend has a match on all black box functions but those code paths would never be executed.
This could lead to confusing bugs between Noir and the backend and it seems hard to communicate to backend implementors.
I'm torn on where this should happen because I don't want aztec_backend to implement keccak itself 😬 I'd probably be fine making a separate PR for this change, just so we can mark it breaking and have a clear CHANGELOG entry. @TomAFrench thoughts?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Of course we would remove the dead code as long as it is integrated in ACVM, so I don't see this as an issue.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This assumes that we are in control of all the backends, but we need to develop as though there are other backends that need to integrate ACVM and they will be confused without accurate documentation & changelog entries.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We could land something like #257 before this and then it wouldn't be an issue.