Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(comptime): Implement blackbox functions in comptime interpreter #6551

Merged
merged 57 commits into from
Nov 26, 2024
Merged
Show file tree
Hide file tree
Changes from 49 commits
Commits
Show all changes
57 commits
Select commit Hold shift + click to select a range
8d29020
Refactor interpret_helper
aakoshh Nov 19, 2024
e579847
Add enum_iter feature to acvm/acir
aakoshh Nov 19, 2024
de15feb
Add test to show which blackbox functions are not implemented
aakoshh Nov 19, 2024
9634781
Redirect range constraint to foreign by name
aakoshh Nov 19, 2024
b4b66a0
Move BrilligBigintSolver to reusable place
aakoshh Nov 19, 2024
e633968
Add get_array_map and get_slice_map. Add BigintSolverWithId to the In…
aakoshh Nov 19, 2024
6e1c9b7
Implement bigint_from_le_bytes
aakoshh Nov 19, 2024
3b42007
Implement bigint ops
aakoshh Nov 19, 2024
1b79080
Test bigint WIP
aakoshh Nov 19, 2024
6cfc97b
Fix clippy
aakoshh Nov 19, 2024
7029dec
Fix array type in the return value
aakoshh Nov 20, 2024
79f8f99
Fix to_le_radix return type
aakoshh Nov 20, 2024
c720512
Not going to implement SchnorrVerify
aakoshh Nov 20, 2024
f323709
Not going to implement XOR + AND
aakoshh Nov 20, 2024
308db81
Implement aes128_encrypt
aakoshh Nov 20, 2024
2d637f3
Implement blake2s
aakoshh Nov 20, 2024
8d8a61a
Implement blake3
aakoshh Nov 20, 2024
11b4e5d
Use get_fixed_array_map in keccakf1600
aakoshh Nov 20, 2024
3f4fbf4
Implement ecdsa_secp256k1
aakoshh Nov 20, 2024
74332cc
Implement ecdsa_secp256r1
aakoshh Nov 20, 2024
dc5864e
Verify the real test data
aakoshh Nov 20, 2024
34bd062
No need to clone
aakoshh Nov 21, 2024
6009323
Test for Sha256
aakoshh Nov 21, 2024
d076c6f
Add macros for generating binary operation matches with type promotion
aakoshh Nov 21, 2024
c8d549a
Implement sha256
aakoshh Nov 21, 2024
e8c2522
Add WillNotImplement error
aakoshh Nov 21, 2024
f153c41
Merge remote-tracking branch 'origin/master' into 6515-interpreter-bl…
aakoshh Nov 21, 2024
29bcc69
Remove leftover macro
aakoshh Nov 21, 2024
e182c84
Allow needless conversion where the same expression is used to handle…
aakoshh Nov 21, 2024
016414b
Differentiate between cmp_all and cmp_num
aakoshh Nov 21, 2024
0f8579c
Shouldn't be any harm in implementing cmp for bool
aakoshh Nov 21, 2024
efe9f27
Implement embedded_curve_add
aakoshh Nov 21, 2024
d89d68d
Implement multi_scalar_mul
aakoshh Nov 21, 2024
ac90774
Test embedded curve ops
aakoshh Nov 21, 2024
09e5cd3
Merge branch 'master' into 6515-interpreter-blackbox
aakoshh Nov 21, 2024
fabd1d6
Allow bool comparison
aakoshh Nov 21, 2024
27faa31
Try blackbox last among builtins.
aakoshh Nov 21, 2024
6f47cf1
Merge branch '6515-interpreter-blackbox' of github.com:noir-lang/noir…
aakoshh Nov 21, 2024
8af33da
Update compiler/noirc_frontend/src/hir/comptime/interpreter/foreign.rs
aakoshh Nov 21, 2024
d111b5e
Change error message
aakoshh Nov 21, 2024
6f9f3c2
Always derive EnumIter
aakoshh Nov 21, 2024
1600977
Use Value::Struct to return BigInt
aakoshh Nov 21, 2024
ac7c669
Only allowing mixed types for bitshift
aakoshh Nov 21, 2024
4549a5e
Merge branch 'master' into 6515-interpreter-blackbox
aakoshh Nov 21, 2024
89bbbda
Fix typo
aakoshh Nov 21, 2024
ff87448
Merge branch '6515-interpreter-blackbox' of github.com:noir-lang/noir…
aakoshh Nov 21, 2024
a33e6a7
Remove unused var
aakoshh Nov 21, 2024
3cb4548
try_into no longer needed
aakoshh Nov 21, 2024
c8c11f6
Merge branch 'master' into 6515-interpreter-blackbox
aakoshh Nov 22, 2024
5d2e834
Renamed Bigint to BigInt
aakoshh Nov 22, 2024
8eec799
Update compiler/noirc_frontend/src/hir/comptime/interpreter/foreign.rs
aakoshh Nov 22, 2024
37d6bb5
Better message in unreachable
aakoshh Nov 22, 2024
6d4be50
Merge branch '6515-interpreter-blackbox' of github.com:noir-lang/noir…
aakoshh Nov 22, 2024
a3cfb0a
Missing ;
aakoshh Nov 22, 2024
3ac8485
Merge remote-tracking branch 'origin/master' into 6515-interpreter-bl…
aakoshh Nov 22, 2024
d2e8164
Fix docs
aakoshh Nov 22, 2024
1744ba5
Merge branch 'master' into 6515-interpreter-blackbox
aakoshh Nov 25, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,8 @@ proptest-derive = "0.4.0"
rayon = "1.8.0"
sha2 = { version = "0.10.6", features = ["compress"] }
sha3 = "0.10.6"
strum = "0.24"
strum_macros = "0.24"

im = { version = "15.1", features = ["serde"] }
tracing = "0.1.40"
Expand Down
4 changes: 2 additions & 2 deletions acvm-repo/acir/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,11 @@ flate2.workspace = true
bincode.workspace = true
base64.workspace = true
serde-big-array = "0.5.1"
strum = { workspace = true }
strum_macros = { workspace = true }

[dev-dependencies]
serde_json = "1.0"
strum = "0.24"
strum_macros = "0.24"
serde-reflection = "0.3.6"
serde-generate = "0.25.1"
fxhash.workspace = true
Expand Down
4 changes: 1 addition & 3 deletions acvm-repo/acir/src/circuit/black_box_functions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,13 @@
//! implemented in more basic constraints.

use serde::{Deserialize, Serialize};
#[cfg(test)]
use strum_macros::EnumIter;

#[allow(clippy::upper_case_acronyms)]
#[derive(Clone, Debug, Hash, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[cfg_attr(test, derive(EnumIter))]
#[derive(Clone, Debug, Hash, Copy, PartialEq, Eq, Serialize, Deserialize, EnumIter)]
pub enum BlackBoxFunc {
/// Ciphers (encrypts) the provided plaintext using AES128 in CBC mode,
/// padding the input using PKCS#7.

Check warning on line 13 in acvm-repo/acir/src/circuit/black_box_functions.rs

View workflow job for this annotation

GitHub Actions / Code

Unknown word (PKCS)
/// - inputs: byte array `[u8; N]`
/// - iv: initialization vector `[u8; 16]`
/// - key: user key `[u8; 16]`
Expand Down
11 changes: 4 additions & 7 deletions acvm-repo/acvm/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,22 +25,19 @@ acvm_blackbox_solver.workspace = true
indexmap = "1.7.0"

[features]
bn254 = [
"acir/bn254",
"brillig_vm/bn254",
"acvm_blackbox_solver/bn254",
]
bn254 = ["acir/bn254", "brillig_vm/bn254", "acvm_blackbox_solver/bn254"]
bls12_381 = [
"acir/bls12_381",
"brillig_vm/bls12_381",
"acvm_blackbox_solver/bls12_381",
]

[dev-dependencies]
ark-bls12-381 = { version = "^0.4.0", default-features = false, features = ["curve"] }
ark-bls12-381 = { version = "^0.4.0", default-features = false, features = [
"curve",
] }
ark-bn254.workspace = true
bn254_blackbox_solver.workspace = true
proptest.workspace = true
zkhash = { version = "^0.2.0", default-features = false }
num-bigint.workspace = true

48 changes: 48 additions & 0 deletions acvm-repo/blackbox_solver/src/bigint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@
}
BlackBoxFunc::BigIntMul => lhs * rhs,
BlackBoxFunc::BigIntDiv => {
lhs * rhs.modpow(&(&modulus - BigUint::from(2_u32)), &modulus)

Check warning on line 87 in acvm-repo/blackbox_solver/src/bigint.rs

View workflow job for this annotation

GitHub Actions / Code

Unknown word (modpow)
} //TODO ensure that modulus is prime
_ => unreachable!("ICE - bigint_op must be called for an operation"),
};
Expand All @@ -97,3 +97,51 @@
Ok(())
}
}

/// Wrapper over the generic bigint solver to automatically assign bigint IDs.
#[derive(Default, Debug, Clone, PartialEq, Eq)]
pub struct BigintSolverWithId {
aakoshh marked this conversation as resolved.
Show resolved Hide resolved
solver: BigIntSolver,
last_id: u32,
}

impl BigintSolverWithId {
pub fn create_bigint_id(&mut self) -> u32 {
let output = self.last_id;
self.last_id += 1;
output
}

pub fn bigint_from_bytes(
&mut self,
inputs: &[u8],
modulus: &[u8],
) -> Result<u32, BlackBoxResolutionError> {
let id = self.create_bigint_id();
self.solver.bigint_from_bytes(inputs, modulus, id)?;
Ok(id)
}

pub fn bigint_to_bytes(&self, input: u32) -> Result<Vec<u8>, BlackBoxResolutionError> {
self.solver.bigint_to_bytes(input)
}

pub fn bigint_op(
&mut self,
lhs: u32,
rhs: u32,
func: BlackBoxFunc,
) -> Result<u32, BlackBoxResolutionError> {
let modulus_lhs = self.solver.get_modulus(lhs, func)?;
let modulus_rhs = self.solver.get_modulus(rhs, func)?;
if modulus_lhs != modulus_rhs {
return Err(BlackBoxResolutionError::Failed(
func,
"moduli should be identical in BigInt operation".to_string(),
));
}
let id = self.create_bigint_id();
self.solver.bigint_op(lhs, rhs, id, func)?;
Ok(id)
}
}
2 changes: 1 addition & 1 deletion acvm-repo/blackbox_solver/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ mod hash;
mod logic;

pub use aes128::aes128_encrypt;
pub use bigint::BigIntSolver;
pub use bigint::{BigIntSolver, BigintSolverWithId};
pub use curve_specific_solver::{BlackBoxFunctionSolver, StubbedBlackBoxSolver};
pub use ecdsa::{ecdsa_secp256k1_verify, ecdsa_secp256r1_verify};
pub use hash::{blake2s, blake3, keccakf1600, sha256_compression};
Expand Down
55 changes: 4 additions & 51 deletions acvm-repo/brillig_vm/src/black_box.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
use acir::brillig::{BlackBoxOp, HeapArray, HeapVector, IntegerBitSize};
use acir::{AcirField, BlackBoxFunc};
use acvm_blackbox_solver::BigIntSolver;
use acvm_blackbox_solver::{
aes128_encrypt, blake2s, blake3, ecdsa_secp256k1_verify, ecdsa_secp256r1_verify, keccakf1600,
sha256_compression, BlackBoxFunctionSolver, BlackBoxResolutionError,
sha256_compression, BigintSolverWithId, BlackBoxFunctionSolver, BlackBoxResolutionError,
};
use num_bigint::BigUint;
use num_traits::Zero;
Expand Down Expand Up @@ -39,6 +38,8 @@
input.iter().map(|&x| x.into()).collect()
}

pub(crate) type BrilligBigintSolver = BigintSolverWithId;

pub(crate) fn evaluate_black_box<F: AcirField, Solver: BlackBoxFunctionSolver<F>>(
op: &BlackBoxOp,
solver: &Solver,
Expand All @@ -56,11 +57,11 @@
})?;
let key: [u8; 16] =
to_u8_vec(read_heap_array(memory, key)).try_into().map_err(|_| {
BlackBoxResolutionError::Failed(bb_func, "Invalid ley length".to_string())
BlackBoxResolutionError::Failed(bb_func, "Invalid key length".to_string())
})?;
let ciphertext = aes128_encrypt(&inputs, iv, key)?;

Check warning on line 62 in acvm-repo/brillig_vm/src/black_box.rs

View workflow job for this annotation

GitHub Actions / Code

Unknown word (ciphertext)

memory.write(outputs.size, ciphertext.len().into());

Check warning on line 64 in acvm-repo/brillig_vm/src/black_box.rs

View workflow job for this annotation

GitHub Actions / Code

Unknown word (ciphertext)
memory.write_slice(memory.read_ref(outputs.pointer), &to_value_vec(&ciphertext));

Ok(())
Expand Down Expand Up @@ -353,54 +354,6 @@
}
}

/// Wrapper over the generic bigint solver to automatically assign bigint ids in brillig
#[derive(Default, Debug, Clone, PartialEq, Eq)]
pub(crate) struct BrilligBigintSolver {
bigint_solver: BigIntSolver,
last_id: u32,
}

impl BrilligBigintSolver {
pub(crate) fn create_bigint_id(&mut self) -> u32 {
let output = self.last_id;
self.last_id += 1;
output
}

pub(crate) fn bigint_from_bytes(
&mut self,
inputs: &[u8],
modulus: &[u8],
) -> Result<u32, BlackBoxResolutionError> {
let id = self.create_bigint_id();
self.bigint_solver.bigint_from_bytes(inputs, modulus, id)?;
Ok(id)
}

pub(crate) fn bigint_to_bytes(&self, input: u32) -> Result<Vec<u8>, BlackBoxResolutionError> {
self.bigint_solver.bigint_to_bytes(input)
}

pub(crate) fn bigint_op(
&mut self,
lhs: u32,
rhs: u32,
func: BlackBoxFunc,
) -> Result<u32, BlackBoxResolutionError> {
let modulus_lhs = self.bigint_solver.get_modulus(lhs, func)?;
let modulus_rhs = self.bigint_solver.get_modulus(rhs, func)?;
if modulus_lhs != modulus_rhs {
return Err(BlackBoxResolutionError::Failed(
func,
"moduli should be identical in BigInt operation".to_string(),
));
}
let id = self.create_bigint_id();
self.bigint_solver.bigint_op(lhs, rhs, id, func)?;
Ok(id)
}
}

fn black_box_function_from_op(op: &BlackBoxOp) -> BlackBoxFunc {
match op {
BlackBoxOp::AES128Encrypt { .. } => BlackBoxFunc::AES128Encrypt,
Expand Down
4 changes: 2 additions & 2 deletions compiler/noirc_frontend/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@ cfg-if.workspace = true
tracing.workspace = true
petgraph = "0.6"
rangemap = "1.4.0"
strum = "0.24"
strum_macros = "0.24"
strum.workspace = true
strum_macros.workspace = true


[dev-dependencies]
Expand Down
10 changes: 10 additions & 0 deletions compiler/noirc_frontend/src/hir/comptime/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,11 @@ pub enum InterpreterError {
item: String,
location: Location,
},
InvalidInComptimeContext {
item: String,
location: Location,
explanation: String,
},
TypeAnnotationsNeededForMethodCall {
location: Location,
},
Expand Down Expand Up @@ -291,6 +296,7 @@ impl InterpreterError {
| InterpreterError::UnsupportedTopLevelItemUnquote { location, .. }
| InterpreterError::ComptimeDependencyCycle { location, .. }
| InterpreterError::Unimplemented { location, .. }
| InterpreterError::InvalidInComptimeContext { location, .. }
| InterpreterError::NoImpl { location, .. }
| InterpreterError::ImplMethodTypeMismatch { location, .. }
| InterpreterError::DebugEvaluateComptime { location, .. }
Expand Down Expand Up @@ -540,6 +546,10 @@ impl<'a> From<&'a InterpreterError> for CustomDiagnostic {
let msg = format!("{item} is currently unimplemented");
CustomDiagnostic::simple_error(msg, String::new(), location.span)
}
InterpreterError::InvalidInComptimeContext { item, location, explanation } => {
let msg = format!("{item} is invalid in comptime context");
CustomDiagnostic::simple_error(msg, explanation.clone(), location.span)
}
InterpreterError::BreakNotInLoop { location } => {
let msg = "There is no loop to break out of!".into();
CustomDiagnostic::simple_error(msg, String::new(), location.span)
Expand Down
Loading
Loading