This repository was 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(stdlib): Add fallback implementation of SHA256
black box function
#407
Merged
Merged
Changes from all commits
Commits
Show all changes
45 commits
Select commit
Hold shift + click to select a range
db1433a
initial
Ethan-000 b97e105
impl padding
Ethan-000 ed1596b
fix bytes
Ethan-000 fbba92b
padding
Ethan-000 2f01ea2
sha256u32
Ethan-000 32612da
unfinished
Ethan-000 c574ad1
.
Ethan-000 4c4e1df
Merge branch 'master' into sha256_fallback
Ethan-000 52ca59d
clippy
Ethan-000 868832b
.
Ethan-000 6b79031
.
Ethan-000 810b73b
.
Ethan-000 e24cbfc
.
Ethan-000 49b6b45
.
Ethan-000 1d51cf3
Merge branch 'master' into sha256_fallback
Ethan-000 895941d
cleanup
Ethan-000 9bc1fbd
Merge branch 'master' into sha256_fallback
Ethan-000 528e746
.
Ethan-000 ec66851
.
Ethan-000 4c011ac
.
Ethan-000 4ad60f1
.
Ethan-000 b6a7759
.
Ethan-000 79cbec1
.
Ethan-000 bba8196
.
Ethan-000 75ea62c
.
Ethan-000 eba6e5b
.
Ethan-000 09d59da
Merge branch 'noir-lang:master' into sha256_fallback
Ethan-000 0b1097e
Merge branch 'master' into sha256_fallback
Ethan-000 adf7a61
.
Ethan-000 6ccc6ca
change wu32 -> uint32
Ethan-000 0eef099
change visibility
Ethan-000 d35c79c
move logic fallbacks to blackbox_fallbacks folder
Ethan-000 a8253d9
remove split & add Copy to uint32
Ethan-000 cb92432
.
Ethan-000 1a90301
fix based on review
Ethan-000 e57e9ce
move bit_decomposition
Ethan-000 48f571c
.
Ethan-000 122816c
.
Ethan-000 4843037
.
Ethan-000 2a37f28
.
Ethan-000 87179b9
sha256 test
Ethan-000 682cdbf
remove genetated file
Ethan-000 acdcbc9
Merge branch 'master' into sha256_fallback
kevaundray 22ae2f3
Merge branch 'master' into sha256_fallback
Ethan-000 e339999
update with master
Ethan-000 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 hidden or 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 hidden or 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 hidden or 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 hidden or 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 hidden or 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,202 @@ | ||
#![cfg(feature = "testing")] | ||
mod solver; | ||
use crate::solver::StubbedBackend; | ||
use acir::{ | ||
circuit::{ | ||
opcodes::{BlackBoxFuncCall, FunctionInput}, | ||
Circuit, Opcode, PublicInputs, | ||
}, | ||
native_types::Witness, | ||
FieldElement, | ||
}; | ||
use acvm::{ | ||
compiler::{compile, CircuitSimplifier}, | ||
pwg::{ACVMStatus, ACVM}, | ||
Language, | ||
}; | ||
use proptest::prelude::*; | ||
use sha2::{Digest, Sha256}; | ||
use std::collections::{BTreeMap, BTreeSet}; | ||
use stdlib::blackbox_fallbacks::UInt32; | ||
|
||
proptest! { | ||
#[test] | ||
fn test_uint32_ror(x in 0..u32::MAX, y in 0..32_u32) { | ||
let fe = FieldElement::from(x as u128); | ||
let w = Witness(1); | ||
let result = x.rotate_right(y); | ||
let sha256_u32 = UInt32::new(w); | ||
let (w, extra_gates, _) = sha256_u32.ror(y, 2); | ||
let witness_assignments = BTreeMap::from([(Witness(1), fe)]).into(); | ||
let mut acvm = ACVM::new(StubbedBackend, extra_gates, witness_assignments); | ||
let solver_status = acvm.solve(); | ||
|
||
prop_assert_eq!(acvm.witness_map().get(&w.get_inner()).unwrap(), &FieldElement::from(result as u128)); | ||
prop_assert_eq!(solver_status, ACVMStatus::Solved, "should be fully solved"); | ||
} | ||
|
||
#[test] | ||
fn test_uint32_euclidean_division(x in 0..u32::MAX, y in 0..u32::MAX) { | ||
let lhs = FieldElement::from(x as u128); | ||
let rhs = FieldElement::from(y as u128); | ||
let w1 = Witness(1); | ||
let w2 = Witness(2); | ||
let q = x.div_euclid(y); | ||
let r = x.rem_euclid(y); | ||
let u32_1 = UInt32::new(w1); | ||
let u32_2 = UInt32::new(w2); | ||
let (q_w, r_w, extra_gates, _) = UInt32::euclidean_division(&u32_1, &u32_2, 3); | ||
let witness_assignments = BTreeMap::from([(Witness(1), lhs),(Witness(2), rhs)]).into(); | ||
let mut acvm = ACVM::new(StubbedBackend, extra_gates, witness_assignments); | ||
let solver_status = acvm.solve(); | ||
|
||
prop_assert_eq!(acvm.witness_map().get(&q_w.get_inner()).unwrap(), &FieldElement::from(q as u128)); | ||
prop_assert_eq!(acvm.witness_map().get(&r_w.get_inner()).unwrap(), &FieldElement::from(r as u128)); | ||
prop_assert_eq!(solver_status, ACVMStatus::Solved, "should be fully solved"); | ||
} | ||
|
||
#[test] | ||
fn test_uint32_add(x in 0..u32::MAX, y in 0..u32::MAX, z in 0..u32::MAX) { | ||
let lhs = FieldElement::from(x as u128); | ||
let rhs = FieldElement::from(y as u128); | ||
let rhs_z = FieldElement::from(z as u128); | ||
let result = FieldElement::from(((x as u128).wrapping_add(y as u128) % (1_u128 << 32)).wrapping_add(z as u128) % (1_u128 << 32)); | ||
let w1 = Witness(1); | ||
let w2 = Witness(2); | ||
let w3 = Witness(3); | ||
let u32_1 = UInt32::new(w1); | ||
let u32_2 = UInt32::new(w2); | ||
let u32_3 = UInt32::new(w3); | ||
let mut gates = Vec::new(); | ||
let (w, extra_gates, num_witness) = u32_1.add(&u32_2, 4); | ||
gates.extend(extra_gates); | ||
let (w2, extra_gates, _) = w.add(&u32_3, num_witness); | ||
gates.extend(extra_gates); | ||
let witness_assignments = BTreeMap::from([(Witness(1), lhs), (Witness(2), rhs), (Witness(3), rhs_z)]).into(); | ||
let mut acvm = ACVM::new(StubbedBackend, gates, witness_assignments); | ||
let solver_status = acvm.solve(); | ||
|
||
prop_assert_eq!(acvm.witness_map().get(&w2.get_inner()).unwrap(), &result); | ||
prop_assert_eq!(solver_status, ACVMStatus::Solved, "should be fully solved"); | ||
} | ||
|
||
#[test] | ||
fn test_uint32_sub(x in 0..u32::MAX, y in 0..u32::MAX, z in 0..u32::MAX) { | ||
let lhs = FieldElement::from(x as u128); | ||
let rhs = FieldElement::from(y as u128); | ||
let rhs_z = FieldElement::from(z as u128); | ||
let result = FieldElement::from(((x as u128).wrapping_sub(y as u128) % (1_u128 << 32)).wrapping_sub(z as u128) % (1_u128 << 32)); | ||
let w1 = Witness(1); | ||
let w2 = Witness(2); | ||
let w3 = Witness(3); | ||
let u32_1 = UInt32::new(w1); | ||
let u32_2 = UInt32::new(w2); | ||
let u32_3 = UInt32::new(w3); | ||
let mut gates = Vec::new(); | ||
let (w, extra_gates, num_witness) = u32_1.sub(&u32_2, 4); | ||
gates.extend(extra_gates); | ||
let (w2, extra_gates, _) = w.sub(&u32_3, num_witness); | ||
gates.extend(extra_gates); | ||
let witness_assignments = BTreeMap::from([(Witness(1), lhs), (Witness(2), rhs), (Witness(3), rhs_z)]).into(); | ||
let mut acvm = ACVM::new(StubbedBackend, gates, witness_assignments); | ||
let solver_status = acvm.solve(); | ||
|
||
prop_assert_eq!(acvm.witness_map().get(&w2.get_inner()).unwrap(), &result); | ||
prop_assert_eq!(solver_status, ACVMStatus::Solved, "should be fully solved"); | ||
} | ||
|
||
#[test] | ||
fn test_uint32_left_shift(x in 0..u32::MAX, y in 0..32_u32) { | ||
let lhs = FieldElement::from(x as u128); | ||
let w1 = Witness(1); | ||
let result = x.overflowing_shl(y).0; | ||
let u32_1 = UInt32::new(w1); | ||
let (w, extra_gates, _) = u32_1.leftshift(y, 2); | ||
let witness_assignments = BTreeMap::from([(Witness(1), lhs)]).into(); | ||
let mut acvm = ACVM::new(StubbedBackend, extra_gates, witness_assignments); | ||
let solver_status = acvm.solve(); | ||
|
||
prop_assert_eq!(acvm.witness_map().get(&w.get_inner()).unwrap(), &FieldElement::from(result as u128)); | ||
prop_assert_eq!(solver_status, ACVMStatus::Solved, "should be fully solved"); | ||
} | ||
|
||
#[test] | ||
fn test_uint32_right_shift(x in 0..u32::MAX, y in 0..32_u32) { | ||
let lhs = FieldElement::from(x as u128); | ||
let w1 = Witness(1); | ||
let result = x.overflowing_shr(y).0; | ||
let u32_1 = UInt32::new(w1); | ||
let (w, extra_gates, _) = u32_1.rightshift(y, 2); | ||
let witness_assignments = BTreeMap::from([(Witness(1), lhs)]).into(); | ||
let mut acvm = ACVM::new(StubbedBackend, extra_gates, witness_assignments); | ||
let solver_status = acvm.solve(); | ||
|
||
prop_assert_eq!(acvm.witness_map().get(&w.get_inner()).unwrap(), &FieldElement::from(result as u128)); | ||
prop_assert_eq!(solver_status, ACVMStatus::Solved, "should be fully solved"); | ||
} | ||
} | ||
|
||
proptest! { | ||
#![proptest_config(ProptestConfig::with_cases(3))] | ||
#[test] | ||
fn test_sha256(input_values in proptest::collection::vec(0..u8::MAX, 1..50)) { | ||
let mut opcodes = Vec::new(); | ||
let mut witness_assignments = BTreeMap::new(); | ||
let mut sha256_input_witnesses: Vec<FunctionInput> = Vec::new(); | ||
let mut correct_result_witnesses: Vec<Witness> = Vec::new(); | ||
let mut output_witnesses: Vec<Witness> = Vec::new(); | ||
|
||
// prepare test data | ||
hash_witnesses!(input_values, witness_assignments, sha256_input_witnesses, correct_result_witnesses, output_witnesses, Sha256); | ||
let sha256_blackbox = Opcode::BlackBoxFuncCall(BlackBoxFuncCall::SHA256 { inputs: sha256_input_witnesses, outputs: output_witnesses }); | ||
opcodes.push(sha256_blackbox); | ||
|
||
// compile circuit | ||
let circuit_simplifier = CircuitSimplifier::new(witness_assignments.len() as u32 + 32); | ||
let circuit = Circuit {current_witness_index: witness_assignments.len() as u32 + 32, | ||
opcodes, public_parameters: PublicInputs(BTreeSet::new()), return_values: PublicInputs(BTreeSet::new()) }; | ||
let circuit = compile(circuit, Language::PLONKCSat{ width: 3 }, does_not_support_sha256, &circuit_simplifier).unwrap().0; | ||
|
||
// solve witnesses | ||
let mut acvm = ACVM::new(StubbedBackend, circuit.opcodes, witness_assignments.into()); | ||
let solver_status = acvm.solve(); | ||
|
||
prop_assert_eq!(solver_status, ACVMStatus::Solved, "should be fully solved"); | ||
} | ||
} | ||
|
||
fn does_not_support_sha256(opcode: &Opcode) -> bool { | ||
!matches!(opcode, Opcode::BlackBoxFuncCall(BlackBoxFuncCall::SHA256 { .. })) | ||
} | ||
|
||
#[macro_export] | ||
macro_rules! hash_witnesses { | ||
( | ||
$input_values:ident, | ||
$witness_assignments:ident, | ||
$input_witnesses: ident, | ||
$correct_result_witnesses:ident, | ||
$output_witnesses:ident, | ||
$hasher:ident | ||
) => { | ||
let mut counter = 0; | ||
let output = $hasher::digest($input_values.clone()); | ||
for inp_v in $input_values { | ||
counter += 1; | ||
let function_input = FunctionInput { witness: Witness(counter), num_bits: 8 }; | ||
$input_witnesses.push(function_input); | ||
$witness_assignments.insert(Witness(counter), FieldElement::from(inp_v as u128)); | ||
} | ||
|
||
for o_v in output { | ||
counter += 1; | ||
$correct_result_witnesses.push(Witness(counter)); | ||
$witness_assignments.insert(Witness(counter), FieldElement::from(o_v as u128)); | ||
} | ||
|
||
for _ in 0..32 { | ||
counter += 1; | ||
$output_witnesses.push(Witness(counter)); | ||
} | ||
}; | ||
} |
This file contains hidden or 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
70 changes: 2 additions & 68 deletions
70
stdlib/src/fallback.rs → ...src/blackbox_fallbacks/logic_fallbacks.rs
This file contains hidden or 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 hidden or 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,7 @@ | ||
mod logic_fallbacks; | ||
mod sha256; | ||
mod uint32; | ||
mod utils; | ||
pub use logic_fallbacks::{and, range, xor}; | ||
pub use sha256::sha256; | ||
pub use uint32::UInt32; |
Oops, something went wrong.
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.
Uh oh!
There was an error while loading. Please reload this page.