Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
45d7c5e
check-witness option for nargo execute
guipublic Dec 10, 2025
4b0cc4c
Merge branch 'master' into gd/issue_10849
guipublic Dec 10, 2025
2a2382f
prover_name and check_witness are not compatible
guipublic Dec 11, 2025
08866fc
Merge branch 'master' into gd/issue_10849
guipublic Dec 11, 2025
c8eb1ff
Merge branch 'master' into gd/issue_10849
guipublic Dec 11, 2025
8e76c60
code review
guipublic Dec 11, 2025
bae602a
use location for error
guipublic Dec 11, 2025
c5bc7be
new 'check-witness' command
guipublic Dec 12, 2025
842bbff
code review
guipublic Dec 12, 2025
e2a30ed
Merge branch 'master' into gd/issue_10849
guipublic Dec 12, 2025
8c7ed7b
clippy
guipublic Dec 12, 2025
bfe7c64
Merge branch 'master' into gd/issue_10849
guipublic Dec 12, 2025
700c588
add support for contract artifacts in check-witness
guipublic Dec 12, 2025
fedc027
exit if any example fails
aakoshh Dec 12, 2025
eda5cd6
Fix circuit.json path
aakoshh Dec 12, 2025
8d816fa
Skip browser example
aakoshh Dec 12, 2025
76e21a5
fix noir-execute in log_and_exec_transcript
guipublic Dec 12, 2025
3937adc
Fix command order in prove_and_verify
aakoshh Dec 12, 2025
dff75a8
add new line
guipublic Dec 12, 2025
11a7529
Merge branch 'master' into gd/issue_10849
guipublic Dec 12, 2025
45b8128
Add 'in' keyword to the fuzzer
aakoshh Dec 12, 2025
be99293
Merge branch 'master' into gd/issue_10849
guipublic Dec 15, 2025
0fe0ee6
code review
guipublic Dec 18, 2025
9f3f968
Merge branch 'master' into gd/issue_10849
guipublic Dec 18, 2025
5faa31b
keep old behavior of noir-execute
guipublic Dec 18, 2025
e77f472
Merge branch 'master' into gd/issue_10849
guipublic Jan 5, 2026
05aa87d
clippy
guipublic Jan 5, 2026
dfd02aa
add unit test for brillig call
guipublic Jan 5, 2026
ef9a43a
Merge branch 'master' into gd/issue_10849
guipublic Jan 5, 2026
65d0838
Merge branch 'master' into gd/issue_10849
guipublic Jan 6, 2026
85ad0ea
Merge branch 'master' into gd/issue_10849
guipublic Jan 9, 2026
741a0bd
Merge branch 'master' into gd/issue_10849
TomAFrench Jan 9, 2026
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
1 change: 1 addition & 0 deletions acvm-repo/acvm/src/compiler/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ use acir::circuit::{AcirOpcodeLocation, AssertionPayload, OpcodeLocation};
pub use optimizers::optimize;
mod optimizers;
mod simulator;
pub mod validator;

pub use simulator::CircuitSimulator;

Expand Down
867 changes: 867 additions & 0 deletions acvm-repo/acvm/src/compiler/validator.rs

Large diffs are not rendered by default.

23 changes: 17 additions & 6 deletions acvm-repo/acvm/src/pwg/blackbox/aes128.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,7 @@
key: &[FunctionInput<F>; 16],
outputs: &[Witness],
) -> Result<(), OpcodeResolutionError<F>> {
let scalars = to_u8_vec(initial_witness, inputs)?;

let iv = to_u8_array(initial_witness, iv)?;
let key = to_u8_array(initial_witness, key)?;

let ciphertext = aes128_encrypt(&scalars, iv, key)?;
let ciphertext = execute_aes128_encryption_opcode(initial_witness, inputs, iv, key)?;

// Write witness assignments
for (output_witness, value) in outputs.iter().zip(ciphertext.into_iter()) {
Expand All @@ -31,6 +26,22 @@
Ok(())
}

pub(crate) fn execute_aes128_encryption_opcode<F: AcirField>(
initial_witness: &WitnessMap<F>,
inputs: &[FunctionInput<F>],
iv: &[FunctionInput<F>; 16],
key: &[FunctionInput<F>; 16],
) -> Result<Vec<u8>, OpcodeResolutionError<F>> {
let scalars = to_u8_vec(initial_witness, inputs)?;

let iv = to_u8_array(initial_witness, iv)?;
let key = to_u8_array(initial_witness, key)?;

let ciphertext = aes128_encrypt(&scalars, iv, key)?;

Ok(ciphertext)
}

#[cfg(test)]
mod tests {
use crate::pwg::blackbox::solve_aes128_encryption_opcode;
Expand All @@ -52,15 +63,15 @@
(Witness(3), FieldElement::from(0x15u128)),
(Witness(4), FieldElement::from(0x16u128)),
(Witness(5), FieldElement::from(0x28u128)),
(Witness(6), FieldElement::from(0xaeu128)),

Check warning on line 66 in acvm-repo/acvm/src/pwg/blackbox/aes128.rs

View workflow job for this annotation

GitHub Actions / Code

Unknown word (xaeu)
(Witness(7), FieldElement::from(0xd2u128)),
(Witness(8), FieldElement::from(0xa6u128)),
(Witness(9), FieldElement::from(0xabu128)),

Check warning on line 69 in acvm-repo/acvm/src/pwg/blackbox/aes128.rs

View workflow job for this annotation

GitHub Actions / Code

Unknown word (xabu)
(Witness(10), FieldElement::from(0xf7u128)),
(Witness(11), FieldElement::from(0x15u128)),
(Witness(12), FieldElement::from(0x88u128)),
(Witness(13), FieldElement::from(0x09u128)),
(Witness(14), FieldElement::from(0xcfu128)),

Check warning on line 74 in acvm-repo/acvm/src/pwg/blackbox/aes128.rs

View workflow job for this annotation

GitHub Actions / Code

Unknown word (xcfu)
(Witness(15), FieldElement::from(0x4fu128)),
(Witness(16), FieldElement::from(0x3cu128)),
// IV {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }
Expand All @@ -86,7 +97,7 @@
// 0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17, 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10 };
(Witness(33), FieldElement::from(0x6bu128)),
(Witness(34), FieldElement::from(0xc1u128)),
(Witness(35), FieldElement::from(0xbeu128)),

Check warning on line 100 in acvm-repo/acvm/src/pwg/blackbox/aes128.rs

View workflow job for this annotation

GitHub Actions / Code

Unknown word (xbeu)
(Witness(36), FieldElement::from(0xe2u128)),
(Witness(37), FieldElement::from(0x2eu128)),
(Witness(38), FieldElement::from(0x40u128)),
Expand All @@ -100,20 +111,20 @@
(Witness(46), FieldElement::from(0x93u128)),
(Witness(47), FieldElement::from(0x17u128)),
(Witness(48), FieldElement::from(0x2au128)),
(Witness(49), FieldElement::from(0xaeu128)),

Check warning on line 114 in acvm-repo/acvm/src/pwg/blackbox/aes128.rs

View workflow job for this annotation

GitHub Actions / Code

Unknown word (xaeu)
(Witness(50), FieldElement::from(0x2du128)),
(Witness(51), FieldElement::from(0x8au128)),
(Witness(52), FieldElement::from(0x57u128)),
(Witness(53), FieldElement::from(0x1eu128)),
(Witness(54), FieldElement::from(0x03u128)),
(Witness(55), FieldElement::from(0xacu128)),

Check warning on line 120 in acvm-repo/acvm/src/pwg/blackbox/aes128.rs

View workflow job for this annotation

GitHub Actions / Code

Unknown word (xacu)
(Witness(56), FieldElement::from(0x9cu128)),
(Witness(57), FieldElement::from(0x9eu128)),
(Witness(58), FieldElement::from(0xb7u128)),
(Witness(59), FieldElement::from(0x6fu128)),
(Witness(60), FieldElement::from(0xacu128)),

Check warning on line 125 in acvm-repo/acvm/src/pwg/blackbox/aes128.rs

View workflow job for this annotation

GitHub Actions / Code

Unknown word (xacu)
(Witness(61), FieldElement::from(0x45u128)),
(Witness(62), FieldElement::from(0xafu128)),

Check warning on line 127 in acvm-repo/acvm/src/pwg/blackbox/aes128.rs

View workflow job for this annotation

GitHub Actions / Code

Unknown word (xafu)
(Witness(63), FieldElement::from(0x8eu128)),
(Witness(64), FieldElement::from(0x51u128)),
(Witness(65), FieldElement::from(0x30u128)),
Expand All @@ -125,13 +136,13 @@
(Witness(71), FieldElement::from(0xe4u128)),
(Witness(72), FieldElement::from(0x11u128)),
(Witness(73), FieldElement::from(0xe5u128)),
(Witness(74), FieldElement::from(0xfbu128)),

Check warning on line 139 in acvm-repo/acvm/src/pwg/blackbox/aes128.rs

View workflow job for this annotation

GitHub Actions / Code

Unknown word (xfbu)
(Witness(75), FieldElement::from(0xc1u128)),
(Witness(76), FieldElement::from(0x19u128)),
(Witness(77), FieldElement::from(0x1au128)),
(Witness(78), FieldElement::from(0x0au128)),
(Witness(79), FieldElement::from(0x52u128)),
(Witness(80), FieldElement::from(0xefu128)),

Check warning on line 145 in acvm-repo/acvm/src/pwg/blackbox/aes128.rs

View workflow job for this annotation

GitHub Actions / Code

Unknown word (xefu)
(Witness(81), FieldElement::from(0xf6u128)),
(Witness(82), FieldElement::from(0x9fu128)),
(Witness(83), FieldElement::from(0x24u128)),
Expand Down
45 changes: 35 additions & 10 deletions acvm-repo/acvm/src/pwg/blackbox/embedded_curve_ops.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,23 @@ pub(super) fn multi_scalar_mul<F: AcirField>(
predicate: FunctionInput<F>,
outputs: (Witness, Witness, Witness),
) -> Result<(), OpcodeResolutionError<F>> {
let (res_x, res_y, is_infinite) =
execute_multi_scalar_mul(backend, initial_witness, points, scalars, predicate)?;

// Insert the resulting point into the witness map
insert_value(&outputs.0, res_x, initial_witness)?;
insert_value(&outputs.1, res_y, initial_witness)?;
insert_value(&outputs.2, is_infinite, initial_witness)?;
Ok(())
}

pub(crate) fn execute_multi_scalar_mul<F: AcirField>(
backend: &impl BlackBoxFunctionSolver<F>,
initial_witness: &WitnessMap<F>,
points: &[FunctionInput<F>],
scalars: &[FunctionInput<F>],
predicate: FunctionInput<F>,
) -> Result<(F, F, F), OpcodeResolutionError<F>> {
let points: Result<Vec<_>, _> =
points.iter().map(|input| input_to_value(initial_witness, *input)).collect();
let points: Vec<_> = points?.into_iter().collect();
Expand All @@ -36,12 +53,7 @@ pub(super) fn multi_scalar_mul<F: AcirField>(
// Call the backend's multi-scalar multiplication function
let (res_x, res_y, is_infinite) =
backend.multi_scalar_mul(&points, &scalars_lo, &scalars_hi, predicate)?;

// Insert the resulting point into the witness map
insert_value(&outputs.0, res_x, initial_witness)?;
insert_value(&outputs.1, res_y, initial_witness)?;
insert_value(&outputs.2, is_infinite, initial_witness)?;
Ok(())
Ok((res_x, res_y, is_infinite))
}

pub(super) fn embedded_curve_add<F: AcirField>(
Expand All @@ -52,6 +64,22 @@ pub(super) fn embedded_curve_add<F: AcirField>(
predicate: FunctionInput<F>,
outputs: (Witness, Witness, Witness),
) -> Result<(), OpcodeResolutionError<F>> {
let (res_x, res_y, res_infinite) =
execute_embedded_curve_add(backend, initial_witness, input1, input2, predicate)?;

insert_value(&outputs.0, res_x, initial_witness)?;
insert_value(&outputs.1, res_y, initial_witness)?;
insert_value(&outputs.2, res_infinite, initial_witness)?;
Ok(())
}

pub(crate) fn execute_embedded_curve_add<F: AcirField>(
backend: &impl BlackBoxFunctionSolver<F>,
initial_witness: &WitnessMap<F>,
input1: [FunctionInput<F>; 3],
input2: [FunctionInput<F>; 3],
predicate: FunctionInput<F>,
) -> Result<(F, F, F), OpcodeResolutionError<F>> {
let input1_x = input_to_value(initial_witness, input1[0])?;
let input1_y = input_to_value(initial_witness, input1[1])?;
let input1_infinite = input_to_value(initial_witness, input1[2])?;
Expand All @@ -69,8 +97,5 @@ pub(super) fn embedded_curve_add<F: AcirField>(
predicate,
)?;

insert_value(&outputs.0, res_x, initial_witness)?;
insert_value(&outputs.1, res_y, initial_witness)?;
insert_value(&outputs.2, res_infinite, initial_witness)?;
Ok(())
Ok((res_x, res_y, res_infinite))
}
41 changes: 30 additions & 11 deletions acvm-repo/acvm/src/pwg/blackbox/hash.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ pub(super) fn solve_generic_256_hash_opcode<F: AcirField>(
}

/// Reads the hash function input from a [`WitnessMap`].
fn get_hash_input<F: AcirField>(
pub(crate) fn get_hash_input<F: AcirField>(
initial_witness: &WitnessMap<F>,
inputs: &[FunctionInput<F>],
message_size: Option<&FunctionInput<F>>,
Expand Down Expand Up @@ -98,10 +98,7 @@ pub(crate) fn solve_sha_256_permutation_opcode<F: AcirField>(
hash_values: &[FunctionInput<F>; 8],
outputs: &[Witness; 8],
) -> Result<(), OpcodeResolutionError<F>> {
let message = to_u32_array(initial_witness, inputs)?;
let mut state = to_u32_array(initial_witness, hash_values)?;

sha256_compression(&mut state, &message);
let state = execute_sha_256_permutation_opcode(initial_witness, inputs, hash_values)?;

for (output_witness, value) in outputs.iter().zip(state.into_iter()) {
insert_value(output_witness, F::from(u128::from(value)), initial_witness)?;
Expand All @@ -110,6 +107,19 @@ pub(crate) fn solve_sha_256_permutation_opcode<F: AcirField>(
Ok(())
}

pub(crate) fn execute_sha_256_permutation_opcode<F: AcirField>(
initial_witness: &WitnessMap<F>,
inputs: &[FunctionInput<F>; 16],
hash_values: &[FunctionInput<F>; 8],
) -> Result<[u32; 8], OpcodeResolutionError<F>> {
let message = to_u32_array(initial_witness, inputs)?;
let mut state = to_u32_array(initial_witness, hash_values)?;

sha256_compression(&mut state, &message);

Ok(state)
}

pub(crate) fn solve_poseidon2_permutation_opcode<F: AcirField>(
backend: &impl BlackBoxFunctionSolver<F>,
initial_witness: &mut WitnessMap<F>,
Expand All @@ -127,19 +137,28 @@ pub(crate) fn solve_poseidon2_permutation_opcode<F: AcirField>(
));
}

let state = execute_poseidon2_permutation_opcode(backend, initial_witness, inputs)?;

// Write witness assignments
for (output_witness, value) in outputs.iter().zip(state.into_iter()) {
insert_value(output_witness, value, initial_witness)?;
}
Ok(())
}

pub(crate) fn execute_poseidon2_permutation_opcode<F: AcirField>(
backend: &impl BlackBoxFunctionSolver<F>,
initial_witness: &WitnessMap<F>,
inputs: &[FunctionInput<F>],
) -> Result<Vec<F>, OpcodeResolutionError<F>> {
// Read witness assignments
let state: Vec<F> = inputs
.iter()
.map(|input| input_to_value(initial_witness, *input))
.collect::<Result<_, _>>()?;

let state = backend.poseidon2_permutation(&state)?;

// Write witness assignments
for (output_witness, value) in outputs.iter().zip(state.into_iter()) {
insert_value(output_witness, value, initial_witness)?;
}
Ok(())
Ok(state)
}

#[cfg(test)]
Expand Down
8 changes: 4 additions & 4 deletions acvm-repo/acvm/src/pwg/blackbox/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,12 @@ use self::{aes128::solve_aes128_encryption_opcode, hash::solve_poseidon2_permuta
use super::{OpcodeNotSolvable, OpcodeResolutionError, insert_value};
use crate::{BlackBoxFunctionSolver, pwg::input_to_value};

mod aes128;
mod embedded_curve_ops;
mod hash;
pub(crate) mod aes128;
pub(crate) mod embedded_curve_ops;
pub(crate) mod hash;
mod logic;
mod range;
mod signature;
pub(crate) mod signature;
pub(crate) mod utils;

use embedded_curve_ops::{embedded_curve_add, multi_scalar_mul};
Expand Down
49 changes: 36 additions & 13 deletions acvm-repo/acvm/src/pwg/blackbox/signature/ecdsa.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,18 +19,43 @@ pub(crate) fn secp256k1_prehashed<F: AcirField>(
predicate: &FunctionInput<F>,
output: Witness,
) -> Result<(), OpcodeResolutionError<F>> {
let is_valid = execute_ecdsa(
initial_witness,
public_key_x_inputs,
public_key_y_inputs,
signature_inputs,
hashed_message_inputs,
predicate,
true,
)?;
insert_value(&output, F::from(is_valid), initial_witness)
}

pub(crate) fn execute_ecdsa<F: AcirField>(
initial_witness: &WitnessMap<F>,
public_key_x_inputs: &[FunctionInput<F>; 32],
public_key_y_inputs: &[FunctionInput<F>; 32],
signature_inputs: &[FunctionInput<F>; 64],
hashed_message_inputs: &[FunctionInput<F>; 32],
predicate: &FunctionInput<F>,
k1: bool,
) -> Result<bool, OpcodeResolutionError<F>> {
let pub_key_x: [u8; 32] = to_u8_array(initial_witness, public_key_x_inputs)?;
let pub_key_y: [u8; 32] = to_u8_array(initial_witness, public_key_y_inputs)?;
let signature: [u8; 64] = to_u8_array(initial_witness, signature_inputs)?;
let hashed_message: [u8; 32] = to_u8_array(initial_witness, hashed_message_inputs)?;
let predicate = input_to_value(initial_witness, *predicate)?.is_one();
let is_valid = if predicate {
ecdsa_secp256k1_verify(&hashed_message, &pub_key_x, &pub_key_y, &signature)?
if k1 {
ecdsa_secp256k1_verify(&hashed_message, &pub_key_x, &pub_key_y, &signature)?
} else {
ecdsa_secp256r1_verify(&hashed_message, &pub_key_x, &pub_key_y, &signature)?
}
} else {
true
};

insert_value(&output, F::from(is_valid), initial_witness)
Ok(is_valid)
}

pub(crate) fn secp256r1_prehashed<F: AcirField>(
Expand All @@ -42,16 +67,14 @@ pub(crate) fn secp256r1_prehashed<F: AcirField>(
predicate: &FunctionInput<F>,
output: Witness,
) -> Result<(), OpcodeResolutionError<F>> {
let pub_key_x: [u8; 32] = to_u8_array(initial_witness, public_key_x_inputs)?;
let pub_key_y: [u8; 32] = to_u8_array(initial_witness, public_key_y_inputs)?;
let signature: [u8; 64] = to_u8_array(initial_witness, signature_inputs)?;
let hashed_message: [u8; 32] = to_u8_array(initial_witness, hashed_message_inputs)?;
let predicate = input_to_value(initial_witness, *predicate)?.is_one();
let is_valid = if predicate {
ecdsa_secp256r1_verify(&hashed_message, &pub_key_x, &pub_key_y, &signature)?
} else {
true
};

let is_valid = execute_ecdsa(
initial_witness,
public_key_x_inputs,
public_key_y_inputs,
signature_inputs,
hashed_message_inputs,
predicate,
false,
)?;
insert_value(&output, F::from(is_valid), initial_witness)
}
2 changes: 1 addition & 1 deletion acvm-repo/acvm/src/pwg/blackbox/signature/mod.rs
Original file line number Diff line number Diff line change
@@ -1 +1 @@
pub(super) mod ecdsa;
pub(crate) mod ecdsa;
14 changes: 10 additions & 4 deletions acvm-repo/acvm/src/pwg/memory_op.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,16 @@ impl<F: AcirField> MemoryOpSolver<F> {
})
}

fn len(&self) -> u32 {
pub(crate) fn len(&self) -> u32 {
u32::try_from(self.block_value.len()).expect("expected a length that fits into a u32")
}

/// Convert a field element into a memory index
/// Only 32 bits values are valid memory indices
fn index_from_field(&self, index: F) -> Result<MemoryIndex, OpcodeResolutionError<F>> {
pub(crate) fn index_from_field(
&self,
index: F,
) -> Result<MemoryIndex, OpcodeResolutionError<F>> {
index.try_to_u32().ok_or_else({
|| OpcodeResolutionError::IndexOutOfBounds {
opcode_location: ErrorLocation::Unresolved,
Expand All @@ -49,7 +52,7 @@ impl<F: AcirField> MemoryOpSolver<F> {

/// Update the 'block_value' map with the provided index/value
/// Returns an 'IndexOutOfBounds' error if the index is outside the block range.
fn write_memory_index(
pub(crate) fn write_memory_index(
&mut self,
index: MemoryIndex,
value: F,
Expand All @@ -68,7 +71,10 @@ impl<F: AcirField> MemoryOpSolver<F> {

/// Returns the value stored in the 'block_value' map for the provided index
/// Returns an 'IndexOutOfBounds' error if the index is not in the map.
fn read_memory_index(&self, index: MemoryIndex) -> Result<F, OpcodeResolutionError<F>> {
pub(crate) fn read_memory_index(
&self,
index: MemoryIndex,
) -> Result<F, OpcodeResolutionError<F>> {
self.block_value.get(index as usize).copied().ok_or(
OpcodeResolutionError::IndexOutOfBounds {
opcode_location: ErrorLocation::Unresolved,
Expand Down
2 changes: 1 addition & 1 deletion acvm-repo/acvm/src/pwg/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ pub(crate) mod arithmetic;
pub(crate) mod brillig;
// black box functions
pub(crate) mod blackbox;
mod memory_op;
pub(crate) mod memory_op;

pub use self::brillig::{BrilligSolver, BrilligSolverStatus};
pub use brillig::ForeignCallWaitInfo;
Expand Down
1 change: 1 addition & 0 deletions examples/oracle_transcript/log_and_exec_transcript.sh
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ nargo execute --skip-underconstrained-check --pedantic-solving --oracle-file Ora

# Also execute through `noir-execute`
noir-execute \
execute \
--artifact-path target/oracle_transcript.json \
--oracle-file Oracle.jsonl \
--prover-file Prover.toml \
Expand Down
Loading
Loading