Skip to content

Commit

Permalink
feat: Sync from noir (#5286)
Browse files Browse the repository at this point in the history
Automated pull of development from the
[noir](https://github.com/noir-lang/noir) programming language, a
dependency of Aztec.
BEGIN_COMMIT_OVERRIDE
feat: add as_slice builtin function, add execution test
(noir-lang/noir#4523)
chore: making docs build before cutting versions
(noir-lang/noir#4568)
chore: fix docker test workflows
(noir-lang/noir#4566)
feat: allow usage of noir `#[test]` syntax in stdlib
(noir-lang/noir#4553)
feat: Add more impls on Option
(noir-lang/noir#4549)
chore: fixing some broken links
(noir-lang/noir#4556)
chore: separate tests for execution failures from compilation failures
(noir-lang/noir#4559)
feat: remove curly braces with fmt
(noir-lang/noir#4529)
fix: Make `nargo` the default binary for cargo run
(noir-lang/noir#4554)
fix: Evaluate operators in globals in types
(noir-lang/noir#4537)
chore: Add more `Hash` impls to stdlib
(noir-lang/noir#4470)
END_COMMIT_OVERRIDE

---------

Co-authored-by: sirasistant <sirasistant@gmail.com>
  • Loading branch information
AztecBot and sirasistant authored Mar 18, 2024
1 parent e146076 commit 86e1a86
Show file tree
Hide file tree
Showing 57 changed files with 1,422 additions and 159 deletions.
1 change: 1 addition & 0 deletions noir/noir-repo/.github/scripts/noir-wasm-build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@
set -eu

.github/scripts/wasm-pack-install.sh
yarn workspace @noir-lang/types build
yarn workspace @noir-lang/noir_wasm build
Original file line number Diff line number Diff line change
Expand Up @@ -451,6 +451,29 @@ impl<'block> BrilligBlock<'block> {
self.convert_ssa_array_len(arguments[0], result_variable.address, dfg);
}
}
Value::Intrinsic(Intrinsic::AsSlice) => {
let source_variable = self.convert_ssa_value(arguments[0], dfg);
let result_ids = dfg.instruction_results(instruction_id);
let destination_len_variable = self.variables.define_single_addr_variable(
self.function_context,
self.brillig_context,
result_ids[0],
dfg,
);
let destination_variable = self.variables.define_variable(
self.function_context,
self.brillig_context,
result_ids[1],
dfg,
);
let source_size_as_register =
self.convert_ssa_array_set(source_variable, destination_variable, None);

// we need to explicitly set the destination_len_variable
self.brillig_context
.mov_instruction(destination_len_variable.address, source_size_as_register);
self.brillig_context.deallocate_register(source_size_as_register);
}
Value::Intrinsic(
Intrinsic::SlicePushBack
| Intrinsic::SlicePopBack
Expand Down Expand Up @@ -610,13 +633,12 @@ impl<'block> BrilligBlock<'block> {
dfg,
);
self.validate_array_index(source_variable, index_register);

self.convert_ssa_array_set(
let source_size_as_register = self.convert_ssa_array_set(
source_variable,
destination_variable,
index_register.address,
value_variable,
Some((index_register.address, value_variable)),
);
self.brillig_context.deallocate_register(source_size_as_register);
}
Instruction::RangeCheck { value, max_bit_size, assert_message } => {
let value = self.convert_ssa_single_addr_value(*value, dfg);
Expand Down Expand Up @@ -811,23 +833,25 @@ impl<'block> BrilligBlock<'block> {

/// Array set operation in SSA returns a new array or slice that is a copy of the parameter array or slice
/// With a specific value changed.
///
/// Returns `source_size_as_register`, which is expected to be deallocated with:
/// `self.brillig_context.deallocate_register(source_size_as_register)`
fn convert_ssa_array_set(
&mut self,
source_variable: BrilligVariable,
destination_variable: BrilligVariable,
index_register: MemoryAddress,
value_variable: BrilligVariable,
) {
opt_index_and_value: Option<(MemoryAddress, BrilligVariable)>,
) -> MemoryAddress {
let destination_pointer = match destination_variable {
BrilligVariable::BrilligArray(BrilligArray { pointer, .. }) => pointer,
BrilligVariable::BrilligVector(BrilligVector { pointer, .. }) => pointer,
_ => unreachable!("ICE: array set returns non-array"),
_ => unreachable!("ICE: array_set SSA returns non-array"),
};

let reference_count = match source_variable {
BrilligVariable::BrilligArray(BrilligArray { rc, .. })
| BrilligVariable::BrilligVector(BrilligVector { rc, .. }) => rc,
_ => unreachable!("ICE: array set on non-array"),
_ => unreachable!("ICE: array_set SSA on non-array"),
};

let (source_pointer, source_size_as_register) = match source_variable {
Expand All @@ -841,7 +865,7 @@ impl<'block> BrilligBlock<'block> {
self.brillig_context.mov_instruction(source_size_register, size);
(pointer, source_size_register)
}
_ => unreachable!("ICE: array set on non-array"),
_ => unreachable!("ICE: array_set SSA on non-array"),
};

// Here we want to compare the reference count against 1.
Expand Down Expand Up @@ -884,18 +908,20 @@ impl<'block> BrilligBlock<'block> {
self.brillig_context.mov_instruction(target_size, source_size_as_register);
self.brillig_context.usize_const_instruction(target_rc, 1_usize.into());
}
_ => unreachable!("ICE: array set on non-array"),
_ => unreachable!("ICE: array_set SSA on non-array"),
}

// Then set the value in the newly created array
self.store_variable_in_array(
destination_pointer,
SingleAddrVariable::new_usize(index_register),
value_variable,
);
if let Some((index_register, value_variable)) = opt_index_and_value {
// Then set the value in the newly created array
self.store_variable_in_array(
destination_pointer,
SingleAddrVariable::new_usize(index_register),
value_variable,
);
}

self.brillig_context.deallocate_register(source_size_as_register);
self.brillig_context.deallocate_register(condition);
source_size_as_register
}

pub(crate) fn store_variable_in_array_with_ctx(
Expand Down Expand Up @@ -1351,6 +1377,7 @@ impl<'block> BrilligBlock<'block> {
Value::Param { .. } | Value::Instruction { .. } => {
// All block parameters and instruction results should have already been
// converted to registers so we fetch from the cache.

self.variables.get_allocation(self.function_context, value_id, dfg)
}
Value::NumericConstant { constant, .. } => {
Expand Down
54 changes: 52 additions & 2 deletions noir/noir-repo/compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1025,7 +1025,13 @@ impl Context {
self.array_set_value(&store_value, result_block_id, &mut var_index)?;

let element_type_sizes = if !can_omit_element_sizes_array(&array_typ) {
Some(self.init_element_type_sizes_array(&array_typ, array_id, None, dfg)?)
let acir_value = self.convert_value(array_id, dfg);
Some(self.init_element_type_sizes_array(
&array_typ,
array_id,
Some(&acir_value),
dfg,
)?)
} else {
None
};
Expand Down Expand Up @@ -1246,7 +1252,8 @@ impl Context {
let read = self.acir_context.read_from_memory(source, &index_var)?;
Ok::<AcirValue, RuntimeError>(AcirValue::Var(read, AcirType::field()))
})?;
self.initialize_array(destination, array_len, Some(AcirValue::Array(init_values.into())))?;
let array: im::Vector<AcirValue> = init_values.into();
self.initialize_array(destination, array_len, Some(AcirValue::Array(array)))?;
Ok(())
}

Expand Down Expand Up @@ -1663,6 +1670,49 @@ impl Context {
};
Ok(vec![AcirValue::Var(self.acir_context.add_constant(len), AcirType::field())])
}
Intrinsic::AsSlice => {
let (slice_contents, slice_typ, block_id) =
self.check_array_is_initialized(arguments[0], dfg)?;
assert!(!slice_typ.is_nested_slice(), "ICE: Nested slice used in ACIR generation");

let result_block_id = self.block_id(&result_ids[1]);
let acir_value = self.convert_value(slice_contents, dfg);

let array_len = if !slice_typ.contains_slice_element() {
slice_typ.flattened_size()
} else {
self.flattened_slice_size(slice_contents, dfg)
};
let slice_length = self.acir_context.add_constant(array_len);
self.copy_dynamic_array(block_id, result_block_id, array_len)?;

let element_type_sizes = if !can_omit_element_sizes_array(&slice_typ) {
Some(self.init_element_type_sizes_array(
&slice_typ,
slice_contents,
Some(&acir_value),
dfg,
)?)
} else {
None
};

let value_types = self.convert_value(slice_contents, dfg).flat_numeric_types();
assert!(
array_len == value_types.len(),
"AsSlice: unexpected length difference: {:?} != {:?}",
array_len,
value_types.len()
);

let result = AcirValue::DynamicArray(AcirDynamicArray {
block_id: result_block_id,
len: value_types.len(),
value_types,
element_type_sizes,
});
Ok(vec![AcirValue::Var(slice_length, AcirType::field()), result])
}
Intrinsic::SlicePushBack => {
// arguments = [slice_length, slice_contents, ...elements_to_push]
let slice_length = self.convert_value(arguments[0], dfg).into_var()?;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ pub(crate) type InstructionId = Id<Instruction>;
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub(crate) enum Intrinsic {
ArrayLen,
AsSlice,
AssertConstant,
SlicePushBack,
SlicePushFront,
Expand All @@ -57,6 +58,7 @@ impl std::fmt::Display for Intrinsic {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Intrinsic::ArrayLen => write!(f, "array_len"),
Intrinsic::AsSlice => write!(f, "as_slice"),
Intrinsic::AssertConstant => write!(f, "assert_constant"),
Intrinsic::SlicePushBack => write!(f, "slice_push_back"),
Intrinsic::SlicePushFront => write!(f, "slice_push_front"),
Expand Down Expand Up @@ -89,6 +91,7 @@ impl Intrinsic {
Intrinsic::ToBits(_) | Intrinsic::ToRadix(_) => true,

Intrinsic::ArrayLen
| Intrinsic::AsSlice
| Intrinsic::SlicePushBack
| Intrinsic::SlicePushFront
| Intrinsic::SlicePopBack
Expand All @@ -109,6 +112,7 @@ impl Intrinsic {
pub(crate) fn lookup(name: &str) -> Option<Intrinsic> {
match name {
"array_len" => Some(Intrinsic::ArrayLen),
"as_slice" => Some(Intrinsic::AsSlice),
"assert_constant" => Some(Intrinsic::AssertConstant),
"apply_range_constraint" => Some(Intrinsic::ApplyRangeConstraint),
"slice_push_back" => Some(Intrinsic::SlicePushBack),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,16 @@ pub(super) fn simplify_call(
SimplifyResult::None
}
}
Intrinsic::AsSlice => {
let slice = dfg.get_array_constant(arguments[0]);
if let Some((slice, element_type)) = slice {
let slice_length = dfg.make_constant(slice.len().into(), Type::length_type());
let new_slice = dfg.make_array(slice, element_type);
SimplifyResult::SimplifiedToMultiple(vec![slice_length, new_slice])
} else {
SimplifyResult::None
}
}
Intrinsic::SlicePushBack => {
let slice = dfg.get_array_constant(arguments[1]);
if let Some((mut slice, element_type)) = slice {
Expand Down
18 changes: 9 additions & 9 deletions noir/noir-repo/docs/docs/noir/standard_library/black_box_fns.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,18 +12,18 @@ The ACVM spec defines a set of blackbox functions which backends will be expecte

Here is a list of the current black box functions:

- [SHA256](./cryptographic_primitives/hashes#sha256)
- [Schnorr signature verification](./cryptographic_primitives/schnorr)
- [Blake2s](./cryptographic_primitives/hashes#blake2s)
- [Blake3](./cryptographic_primitives/hashes#blake3)
- [Pedersen Hash](./cryptographic_primitives/hashes#pedersen_hash)
- [Pedersen Commitment](./cryptographic_primitives/hashes#pedersen_commitment)
- [ECDSA signature verification](./cryptographic_primitives/ecdsa_sig_verification)
- [Fixed base scalar multiplication](./cryptographic_primitives/scalar)
- [SHA256](./cryptographic_primitives/hashes.mdx#sha256)
- [Schnorr signature verification](./cryptographic_primitives/schnorr.mdx)
- [Blake2s](./cryptographic_primitives/hashes.mdx#blake2s)
- [Blake3](./cryptographic_primitives/hashes.mdx#blake3)
- [Pedersen Hash](./cryptographic_primitives/hashes.mdx#pedersen_hash)
- [Pedersen Commitment](./cryptographic_primitives/hashes.mdx#pedersen_commitment)
- [ECDSA signature verification](./cryptographic_primitives/ecdsa_sig_verification.mdx)
- [Fixed base scalar multiplication](./cryptographic_primitives/scalar.mdx)
- AND
- XOR
- RANGE
- [Keccak256](./cryptographic_primitives/hashes#keccak256)
- [Keccak256](./cryptographic_primitives/hashes.mdx#keccak256)
- [Recursive proof verification](./recursion)

Most black box functions are included as part of the Noir standard library, however `AND`, `XOR` and `RANGE` are used as part of the Noir language syntax. For instance, using the bitwise operator `&` will invoke the `AND` black box function.
Expand Down
2 changes: 1 addition & 1 deletion noir/noir-repo/docs/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
"build": "yarn preprocess && yarn version::stables && docusaurus build",
"version::stables": "ts-node ./scripts/setStable.ts",
"serve": "serve build",
"version": "yarn preprocess && docusaurus docs:version"
"version": "yarn preprocess && docusaurus build && docusaurus docs:version"
},
"dependencies": {
"@docusaurus/core": "^3.0.1",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,18 +12,18 @@ The ACVM spec defines a set of blackbox functions which backends will be expecte

Here is a list of the current black box functions:

- [SHA256](./cryptographic_primitives/hashes#sha256)
- [Schnorr signature verification](./cryptographic_primitives/schnorr)
- [Blake2s](./cryptographic_primitives/hashes#blake2s)
- [Blake3](./cryptographic_primitives/hashes#blake3)
- [Pedersen Hash](./cryptographic_primitives/hashes#pedersen_hash)
- [Pedersen Commitment](./cryptographic_primitives/hashes#pedersen_commitment)
- [ECDSA signature verification](./cryptographic_primitives/ecdsa_sig_verification)
- [Fixed base scalar multiplication](./cryptographic_primitives/scalar)
- [SHA256](./cryptographic_primitives/hashes.mdx#sha256)
- [Schnorr signature verification](./cryptographic_primitives/schnorr.mdx)
- [Blake2s](./cryptographic_primitives/hashes.mdx#blake2s)
- [Blake3](./cryptographic_primitives/hashes.mdx#blake3)
- [Pedersen Hash](./cryptographic_primitives/hashes.mdx#pedersen_hash)
- [Pedersen Commitment](./cryptographic_primitives/hashes.mdx#pedersen_commitment)
- [ECDSA signature verification](./cryptographic_primitives/ecdsa_sig_verification.mdx)
- [Fixed base scalar multiplication](./cryptographic_primitives/scalar.mdx)
- AND
- XOR
- RANGE
- [Keccak256](./cryptographic_primitives/hashes#keccak256)
- [Keccak256](./cryptographic_primitives/hashes.mdx#keccak256)
- [Recursive proof verification](./recursion)

Most black box functions are included as part of the Noir standard library, however `AND`, `XOR` and `RANGE` are used as part of the Noir language syntax. For instance, using the bitwise operator `&` will invoke the `AND` black box function.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,18 +12,18 @@ The ACVM spec defines a set of blackbox functions which backends will be expecte

Here is a list of the current black box functions:

- [SHA256](./cryptographic_primitives/hashes#sha256)
- [Schnorr signature verification](./cryptographic_primitives/schnorr)
- [Blake2s](./cryptographic_primitives/hashes#blake2s)
- [Blake3](./cryptographic_primitives/hashes#blake3)
- [Pedersen Hash](./cryptographic_primitives/hashes#pedersen_hash)
- [Pedersen Commitment](./cryptographic_primitives/hashes#pedersen_commitment)
- [ECDSA signature verification](./cryptographic_primitives/ecdsa_sig_verification)
- [Fixed base scalar multiplication](./cryptographic_primitives/scalar)
- [SHA256](./cryptographic_primitives/hashes.mdx#sha256)
- [Schnorr signature verification](./cryptographic_primitives/schnorr.mdx)
- [Blake2s](./cryptographic_primitives/hashes.mdx#blake2s)
- [Blake3](./cryptographic_primitives/hashes.mdx#blake3)
- [Pedersen Hash](./cryptographic_primitives/hashes.mdx#pedersen_hash)
- [Pedersen Commitment](./cryptographic_primitives/hashes.mdx#pedersen_commitment)
- [ECDSA signature verification](./cryptographic_primitives/ecdsa_sig_verification.mdx)
- [Fixed base scalar multiplication](./cryptographic_primitives/scalar.mdx)
- AND
- XOR
- RANGE
- [Keccak256](./cryptographic_primitives/hashes#keccak256)
- [Keccak256](./cryptographic_primitives/hashes.mdx#keccak256)
- [Recursive proof verification](./recursion)

Most black box functions are included as part of the Noir standard library, however `AND`, `XOR` and `RANGE` are used as part of the Noir language syntax. For instance, using the bitwise operator `&` will invoke the `AND` black box function.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
TypeDoc added this file to prevent GitHub Pages from using Jekyll. You can turn off this behavior by setting the `githubPages` option to false.
Loading

0 comments on commit 86e1a86

Please sign in to comment.