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: Add HashMap to the stdlib #4242

Merged
merged 12 commits into from
Feb 23, 2024

Conversation

NikitaMasych
Copy link
Contributor

Description

This PR shall bring HashMap into the stdlib of Noir.

Problem*

Resolves #4241

Summary*

Implementation of HashMap with open addressing and quadratic probing scheme. Since Noir requires knowing loop bounds (and recursive calls) at compile time, HashMap is of fixed capacity and no dynamic resize is accomplished with regard to load factor.

Furthermore, contribution includes implementation of PedersenHasher to be used for now. One can examine potentially better and less heavy prehash functions.

I tried to conform with best practices of engineering, however since Noir is in rapid development, there are certain things which may be optimized in future, both from the code style and performance point of view.

Additional Context

I put the PedersenHasher among the poseidon.nr and mimc.nr, so one can consider moving declaration of other pedersen-related functionality there, however that would be a breaking change.

Documentation*

Check one:

  • No documentation needed.
  • Documentation included in this PR.
  • [Exceptional Case] Documentation to be submitted in a separate PR.

PR Checklist*

  • I have tested the changes locally.
  • I have formatted the changes with Prettier and/or cargo fmt on default settings.

Copy link
Contributor

@jfecher jfecher left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks like a very good hashmap implementation, thank you!

My main note that is not mentioned in my comments was that I think it may be too early to introduce a Map trait - I don't think there is need for one now when there is only one map type. Rust for example gets by without a similar trait despite having two map types so I think we can avoid the extra complexity for now.

noir_stdlib/src/collections/map.nr Outdated Show resolved Hide resolved
noir_stdlib/src/collections/map.nr Outdated Show resolved Hide resolved
noir_stdlib/src/collections/map.nr Outdated Show resolved Hide resolved
noir_stdlib/src/hash.nr Outdated Show resolved Hide resolved
noir_stdlib/src/hash.nr Show resolved Hide resolved
noir_stdlib/src/hash/pedersen.nr Show resolved Hide resolved
test_programs/execution_success/hashmap/src/main.nr Outdated Show resolved Hide resolved
@jfecher jfecher changed the title feat: HashMap feat: Add HashMap to the stdlib Feb 2, 2024
@NikitaMasych
Copy link
Contributor Author

Thank you for the feedback @jfecher! I will try to apply your notes and advises as soon as I can.

noir_stdlib/src/collections/map.nr Outdated Show resolved Hide resolved
noir_stdlib/src/collections/map.nr Outdated Show resolved Hide resolved
noir_stdlib/src/collections/map.nr Outdated Show resolved Hide resolved
noir_stdlib/src/hash/pedersen.nr Show resolved Hide resolved
noir_stdlib/src/hash.nr Show resolved Hide resolved
}

// Get the value by key. If it does not exist, returns none().
pub fn get(self, key: K) -> Option<V>

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Howdy. This is a really nice piece of work! I have some suggestions to how the performance of map can be improved, but please don't take this as criticism; I'm very impressed with the quality of this PR.

From what I can understand, the get method is linear-time in the size of N due to the for loop.

It is possible to create a map abstraction where accessing the map can be done in a constant number of constraints regardless of N, by using a doubly-linked-list data structure.

The idea is to store the map key/values in a size-N linked list, where the list is sorted by key value (assuming the key is a field element, or is hashed into a field element).

When get-ing a value via its key, a simple array lookup suffices if the key is present. If the key is not present, it is possible to prove that the requested key value lies between two adjacent nodes in the linked list.

A rough proof of concept is at https://gist.github.com/zac-williamson/4bee81b912471395b4e3c9b6029bad81 . It requires noir version 0.23 and is quite inefficient because of a bug in the noir compiler (#4244)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @zac-williamson, both approaches in Noir would have trade-offs. Quadratic (and linear) probing hashmaps typically rely on being mostly empty (typically >50%) so that their search is not linear. When this is true, it is more likely an elements first hash will lead to an empty spot and we still have amortized constant time. The lack of break in Noir however means even after finding a spot we'd still be looping doing nothing. Moreover, Noir cannot dynamically resize hashmaps like other languages so we also will most likely need to panic when the map starts to become filled over a certain percentage.

For the approach of using a list for each bucket, we can emulate list with a BoundedVec as long as we choose a maximum size for buckets, which we'll need anyway since we cannot reallocate and Noir similarly doesn't support linked lists directly. So our overall map will resemble HashMap<K, V, Len, BucketLen>. Similar to the quadratic probing approach, we'll need to panic when the map becomes filled, but this time we'll only need to panic if the item count exceeds Len or if the items in one bucket exceeds BucketLen. One issue with this method is that since the overall hashmap size is separate from the bucket size, it is less clear to users how much data they can actually put in this fixed-size hashmap since it now depends on how many hash collisions there are. E.g. if the map has a fixed size of 100 and a bucket size of just 2, we can still panic (assert(false)) if just 3 elements are inserted which happen to have the same hash (modulo 100). I think this can make the map less reliable in comparison.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure I follow what you're saying @jfecher . It's possible to implement linked lists in Noir with constant-time access (see the gist I linked), which means the overall map does not resemble HashMap as the access time is fixed regardless of the maximum size of the map or the number of filled elements.

Building a linked list out of arrays and using the linked list to implement a map will almost always be faster than iterating over the map in linear time.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure I follow what you wrote about collisions @jfecher . I was assuming we use a cryptographic hash function with collision resistance; we can assume there won't be any collisions unless the key is identical (which can be explicitly handled). Is that not your understanding as well?

Copy link
Contributor

@jfecher jfecher Feb 6, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@zac-williamson sorry for deleting my last comment - I hadn't intended for you to reply yet. I realized I needed to stop and look at your example in more detail when I saw it used unconstrained functions and looped over the current length of the map.

With regard to a cryptographic hash function, there will always be collisions in a hash map because a hash map will take a hash and perform hash % self.capacity (to figure out which slot to insert the item into) which will lead to more collisions as the map fills regardless of the hash method used (although cryptographic hashes are still an improvement).

Copy link

@zac-williamson zac-williamson Mar 15, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @zac-williamson, both approaches in Noir would have trade-offs. Quadratic (and linear) probing hashmaps typically rely on being mostly empty (typically >50%) so that their search is not linear. When this is true, it is more likely an elements first hash will lead to an empty spot and we still have amortized constant time. The lack of break in Noir however means even after finding a spot we'd still be looping doing nothing. Moreover, Noir cannot dynamically resize hashmaps like other languages so we also will most likely need to panic when the map starts to become filled over a certain percentage.

For the approach of using a list for each bucket, we can emulate list with a BoundedVec as long as we choose a maximum size for buckets, which we'll need anyway since we cannot reallocate and Noir similarly doesn't support linked lists directly. So our overall map will resemble HashMap<K, V, Len, BucketLen>. Similar to the quadratic probing approach, we'll need to panic when the map becomes filled, but this time we'll only need to panic if the item count exceeds Len or if the items in one bucket exceeds BucketLen. One issue with this method is that since the overall hashmap size is separate from the bucket size, it is less clear to users how much data they can actually put in this fixed-size hashmap since it now depends on how many hash collisions there are. E.g. if the map has a fixed size of 100 and a bucket size of just 2, we can still panic (assert(false)) if just 3 elements are inserted which happen to have the same hash (modulo 100). I think this can make the map less reliable in comparison.

I think the confusion here is perhaps my misuse of the term hashmap. The object I implemented merely emulates the behaviour of a hashmap.

I don’t derive a position in the map by taking hash % array size.

instead, each hash is linked to a specific array element.

access is still O(N) but only in the unconstrained function. The part that needs to be constrained is O(1)

@jfecher
Copy link
Contributor

jfecher commented Feb 6, 2024

I wonder if we can take inspiration from @zac-williamson's proof of concept and have an unconstrained method return the final index of the key. Then in constrained code we can assert that it is correct and perform the get/insert.

noir_stdlib/src/collections/map.nr Outdated Show resolved Hide resolved
noir_stdlib/src/collections/map.nr Outdated Show resolved Hide resolved
noir_stdlib/src/collections/map.nr Outdated Show resolved Hide resolved
noir_stdlib/src/collections/map.nr Outdated Show resolved Hide resolved
noir_stdlib/src/collections/map.nr Outdated Show resolved Hide resolved
@NikitaMasych
Copy link
Contributor Author

Hi guys, sorry for the delay, apparently I've got a virus. Applied new @jfecher 's review notes, fixed incorrect call from execution_success intended to fail load factor test.

Note: I did force push to remove merge commit (rebase instead)

@NikitaMasych
Copy link
Contributor Author

I wonder if we can take inspiration from @zac-williamson's proof of concept and have an unconstrained method return the final index of the key. Then in constrained code we can assert that it is correct and perform the get/insert.

It is indeed an interesting concept and shall be investigated further; now we have high-coupling reasoned by sequential execution in Noir, which complexifies (or makes question necessity of such) splitting index computation.

Copy link
Contributor

@jfecher jfecher left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks!

As @zac-williamson there is room for improvement performance-wise in the future, but as long as we don't guarantee a particular implementation in Noir we should be free to swap out the internals later. I think this is a good base for now though. I'll add some more Hash impls and documentation in a separate PR.

@jfecher
Copy link
Contributor

jfecher commented Feb 14, 2024

Looks like you have a test failure in CI:

error: Only sized types may be used in the entry point to a program
   ┌─ /home/runner/work/noir/noir/test_programs/execution_success/hashmap/src/main.nr:31:17
   │
31 │ fn main(input: [Entry; HASHMAP_LEN]) {
   │                 ----- Slices, references, or any type containing them may not be used in main or a contract function
   │

auto-merge was automatically disabled February 14, 2024 15:50

Head branch was pushed to by a user without write access

@jfecher
Copy link
Contributor

jfecher commented Feb 14, 2024

Thanks for the fix, I just realized that is a new bug in master.

auto-merge was automatically disabled February 14, 2024 16:10

Head branch was pushed to by a user without write access

@NikitaMasych
Copy link
Contributor Author

Rebased with regard to current master and applied small code style fix (unused zeroed), now clear from my side to be merged

@NikitaMasych
Copy link
Contributor Author

Hi guys, as I see this PR cannot be auto-merged due to stdlib producing warnings test fail. It is indeed the responsibility of this contribution code. There are 3 entries with equal issue: unused variable self in the methods:

Two in src/collections/map.nr:

impl<K, V, N, B, H> HashMap<K, V, N, B> {
    ...
    // Get the compile-time map capacity.
    pub fn capacity(self) -> u64 {
        N
    }
    ...
    // Probing scheme: quadratic function.
    // We use 0.5 constant near variadic attempt and attempt^2 monomials.
    // This ensures good uniformity of distribution for table sizes
    // equal to prime numbers or powers of two. 
    fn quadratic_probe(self, hash: u64, attempt: u64) -> u64 {
        (hash + (attempt + attempt * attempt) / 2) % N
    }
    ...

And one in src/hash.nr:

trait BuildHasher<H> where H: Hasher{
    fn build_hasher(self) -> H;
}

struct BuildHasherDefault<H>;

impl<H> BuildHasher<H> for BuildHasherDefault<H>
where 
    H: Hasher + Default
{
    fn build_hasher(self) -> H{
        H::default()
    }
}

Vindication to the former is that it is required to know generic N, binded to particular instance of the HashMap (analogical to static methods in other languages, in case self is not utilized), and, regarding latter, design to use self is also because one can potentially implement BuildHasher trait with a certain state, needed to be accessed via self. syntax (think of a randomization seed for example).

Ergo I see several options on what could be done here:

  1. Manually merge this PR

  2. Add to the Noir attribute/macro similar to as in Rust: #[allow(unused_variables)]

  3. Modify existing implementation the following way, mitigating usage of self:

    1. Remove capacity method, since it cannot be refactored in other way and is auxiliary.
    2. Update quadratic_probe as
      fn quadratic_probe(table_size: u64, hash: u64, attempt: u64) -> u64 {
          (hash + (attempt + attempt * attempt) / 2) % table_size
      }
      And call it like:
      let index = HashMap::quadratic_probe(N, hash, attempt as u64);
      Instead of the previous:
      let index = self.quadratic_probe(hash, attempt as u64);
    3. Remove self from the signature of BuildHasher trait; that is however not a very thoughtful in a long-term design solution.

What option do you think we can go along with, in order to deliver this PR's functionality?

@jfecher
Copy link
Contributor

jfecher commented Feb 22, 2024

@NikitaMasych you can also rename self to _self: Self to silence the warning

auto-merge was automatically disabled February 22, 2024 15:53

Head branch was pushed to by a user without write access

@NikitaMasych
Copy link
Contributor Author

@NikitaMasych you can also rename self to _self: Self to silence the warning

Thank you for advice! I hoped there is something like that.

@NikitaMasych
Copy link
Contributor Author

@NikitaMasych you can also rename self to _self: Self to silence the warning

It would be valuable if added to https://noir-lang.org/docs

@jfecher
Copy link
Contributor

jfecher commented Feb 23, 2024

It would be valuable if added to https://noir-lang.org/docs

@noir-lang/developerrelations commenting to log this issue for later

@NikitaMasych
Copy link
Contributor Author

NikitaMasych commented Feb 23, 2024

@jfecher it looks like now there are no problems with tests failing, including due to warnings - can you set auto-merge this PR or you need to put it on hold?

@jfecher jfecher added this pull request to the merge queue Feb 23, 2024
@jfecher
Copy link
Contributor

jfecher commented Feb 23, 2024

@NikitaMasych queued to merge now 🙂

Merged via the queue into noir-lang:master with commit 650ffc5 Feb 23, 2024
44 of 45 checks passed
TomAFrench added a commit that referenced this pull request Feb 26, 2024
* master: (39 commits)
  chore: remove unwanted prints (#4419)
  fix: remove print from monomorphization pass (#4417)
  chore(ssa): Remove mem2reg run before flattening (#4415)
  feat: Add HashMap to the stdlib (#4242)
  fix!: Ban Fields in for loop indices and bitwise ops (#4376)
  chore: Add #[recursive] Explainer to Documentation (#4399)
  feat(ci): Use wasm-opt when compiling wasm packages (#4334)
  fix: add handling to `noir_wasm` for projects without dependencies (#4344)
  chore: rename parameter 'filter' to 'level' in 'init_log_level' (#4403)
  chore!: bump msrv to 1.73.0 (#4406)
  chore: fix docker test workflows (#4308)
  chore: Update Vec docs (#4400)
  feat: update error message when trying to load workspace as dependency (#4393)
  chore: bump webpack dependencies (#4346)
  fix: correct invalid brillig codegen for `EmbeddedCurvePoint.add` (#4382)
  chore: remove dependency on generational-arena (#4207)
  fix(docs): update install versions (#4396)
  fix: Enforce matching types of binary ops in SSA (#4391)
  fix(docs): Update noirjs_app for 0.23 (#4378)
  chore(ci): add alerts for failed publishes (#4388)
  ...
TomAFrench added a commit that referenced this pull request Feb 26, 2024
* master:
  chore(ci): prevent msrv checks from blocking PRs (#4414)
  feat: expose separate functions to compile programs vs contracts in `noir_wasm` (#4413)
  chore: do not panic when dividing by zero (#4424)
  chore: remove unwanted prints (#4419)
  fix: remove print from monomorphization pass (#4417)
  chore(ssa): Remove mem2reg run before flattening (#4415)
  feat: Add HashMap to the stdlib (#4242)
TomAFrench added a commit that referenced this pull request Feb 26, 2024
* master: (440 commits)
  chore: remove duplicate `parse_all` function in wasm compiler (#4411)
  chore(ci): prevent msrv checks from blocking PRs (#4414)
  feat: expose separate functions to compile programs vs contracts in `noir_wasm` (#4413)
  chore: do not panic when dividing by zero (#4424)
  chore: remove unwanted prints (#4419)
  fix: remove print from monomorphization pass (#4417)
  chore(ssa): Remove mem2reg run before flattening (#4415)
  feat: Add HashMap to the stdlib (#4242)
  fix!: Ban Fields in for loop indices and bitwise ops (#4376)
  chore: Add #[recursive] Explainer to Documentation (#4399)
  feat(ci): Use wasm-opt when compiling wasm packages (#4334)
  fix: add handling to `noir_wasm` for projects without dependencies (#4344)
  chore: rename parameter 'filter' to 'level' in 'init_log_level' (#4403)
  chore!: bump msrv to 1.73.0 (#4406)
  chore: fix docker test workflows (#4308)
  chore: Update Vec docs (#4400)
  feat: update error message when trying to load workspace as dependency (#4393)
  chore: bump webpack dependencies (#4346)
  fix: correct invalid brillig codegen for `EmbeddedCurvePoint.add` (#4382)
  chore: remove dependency on generational-arena (#4207)
  ...
TomAFrench added a commit that referenced this pull request Feb 27, 2024
* master: (45 commits)
  chore(docs): correct 'Edit this page' URL for dev docs (#4433)
  feat: Sync from aztec-packages (#4390)
  chore(docs): fix external contributor force push workflow (#4437)
  chore!: Remove empty value from bounded vec (#4431)
  chore: nargo fmt (#4434)
  feat: add poseidon2 opcode implementation for acvm/brillig, and Noir (#4398)
  fix: remove panic when generic array length is not resolvable (#4408)
  chore(ci): enforce formatting of noir code in CI (#4422)
  fix: correct formatting for databus visibility types (#4423)
  chore: remove duplicate `parse_all` function in wasm compiler (#4411)
  chore(ci): prevent msrv checks from blocking PRs (#4414)
  feat: expose separate functions to compile programs vs contracts in `noir_wasm` (#4413)
  chore: do not panic when dividing by zero (#4424)
  chore: remove unwanted prints (#4419)
  fix: remove print from monomorphization pass (#4417)
  chore(ssa): Remove mem2reg run before flattening (#4415)
  feat: Add HashMap to the stdlib (#4242)
  fix!: Ban Fields in for loop indices and bitwise ops (#4376)
  chore: Add #[recursive] Explainer to Documentation (#4399)
  feat(ci): Use wasm-opt when compiling wasm packages (#4334)
  ...
TomAFrench added a commit that referenced this pull request Feb 27, 2024
* master: (46 commits)
  feat: Sync from aztec-packages (#4438)
  chore(docs): correct 'Edit this page' URL for dev docs (#4433)
  feat: Sync from aztec-packages (#4390)
  chore(docs): fix external contributor force push workflow (#4437)
  chore!: Remove empty value from bounded vec (#4431)
  chore: nargo fmt (#4434)
  feat: add poseidon2 opcode implementation for acvm/brillig, and Noir (#4398)
  fix: remove panic when generic array length is not resolvable (#4408)
  chore(ci): enforce formatting of noir code in CI (#4422)
  fix: correct formatting for databus visibility types (#4423)
  chore: remove duplicate `parse_all` function in wasm compiler (#4411)
  chore(ci): prevent msrv checks from blocking PRs (#4414)
  feat: expose separate functions to compile programs vs contracts in `noir_wasm` (#4413)
  chore: do not panic when dividing by zero (#4424)
  chore: remove unwanted prints (#4419)
  fix: remove print from monomorphization pass (#4417)
  chore(ssa): Remove mem2reg run before flattening (#4415)
  feat: Add HashMap to the stdlib (#4242)
  fix!: Ban Fields in for loop indices and bitwise ops (#4376)
  chore: Add #[recursive] Explainer to Documentation (#4399)
  ...
@jfecher jfecher mentioned this pull request Feb 29, 2024
5 tasks
github-merge-queue bot pushed a commit that referenced this pull request Mar 8, 2024
# Description

## Problem\*

## Summary\*

Adds docs for #4242

I've also edited the interface for `entries`, `keys`, and `values` to
return `BoundedVec`s instead of arrays with optional elements. This is
much more natural I think. I originally intended this for a separate PR,
but I didn't want to write documentation for the old version of these
functions only to immediately have to edit them afterward.

## Additional Context



## Documentation\*

Check one:
- [ ] No documentation needed.
- [x] Documentation included in this PR.
- [ ] **[Exceptional Case]** Documentation to be submitted in a separate
PR.

# PR Checklist\*

- [x] I have tested the changes locally.
- [x] I have formatted the changes with [Prettier](https://prettier.io/)
and/or `cargo fmt` on default settings.

---------

Co-authored-by: Tom French <15848336+TomAFrench@users.noreply.github.com>
github-merge-queue bot pushed a commit that referenced this pull request Mar 11, 2024
🤖 I have created a release *beep* *boop*
---


<details><summary>0.25.0</summary>

## [0.25.0](v0.24.0...v0.25.0)
(2024-03-11)


### ⚠ BREAKING CHANGES

* Internal as a macro
(AztecProtocol/aztec-packages#4898)
* reserve `unchecked` keyword
([#4432](#4432))
* Remove empty value from bounded vec
([#4431](#4431))
* Ban Fields in for loop indices and bitwise ops
([#4376](#4376))
* bump msrv to 1.73.0
([#4406](#4406))
* **ci:** Bump MSRV to 1.72.1 and enforce that ACVM can be published
using updated lockfile
([#4385](#4385))
* Restrict bit sizes
([#4235](#4235))
* move noir out of yarn-project
(AztecProtocol/aztec-packages#4479)
* note type ids
(AztecProtocol/aztec-packages#4500)

### Features

* Add eddsa_poseidon_to_pub function to stdlib with test + docs
([#4473](#4473))
([00d2c32](00d2c32))
* Add HashMap to the stdlib
([#4242](#4242))
([650ffc5](650ffc5))
* Add option to set max memory for bb.js
([#4227](#4227))
([8a6b131](8a6b131))
* Add overflow and underflow checks for unsigned integers in brillig
([#4445](#4445))
([21fc4b8](21fc4b8))
* Add poseidon2 opcode implementation for acvm/brillig, and Noir
([#4398](#4398))
([10e8292](10e8292))
* Added cast opcode and cast calldata
(AztecProtocol/aztec-packages#4423)
([78ef013](78ef013))
* Allow type aliases to reference other aliases
([#4353](#4353))
([c44ef14](c44ef14))
* Backpropagate constants in ACIR during optimization
([#3926](#3926))
([aad0da0](aad0da0))
* **ci:** Use wasm-opt when compiling wasm packages
([#4334](#4334))
([e382921](e382921))
* DAP Preflight and debugger compilation options
([#4185](#4185))
([e0ad0b2](e0ad0b2))
* Expose separate functions to compile programs vs contracts in
`noir_wasm` ([#4413](#4413))
([7cd5fdb](7cd5fdb))
* Internal as a macro
(AztecProtocol/aztec-packages#4898)
([5f57ebb](5f57ebb))
* Note type ids
(AztecProtocol/aztec-packages#4500)
([78ef013](78ef013))
* Restrict bit sizes
([#4235](#4235))
([1048f81](1048f81))
* Run tests in parallel in `nargo test`
([#4484](#4484))
([761734e](761734e))
* Skip redundant range checks in brillig
([#4460](#4460))
([cb4c1c5](cb4c1c5))
* Sync from aztec-packages
([#4483](#4483))
([fe8f277](fe8f277))
* Track stack frames and their variables in the debugger
([#4188](#4188))
([ae1a9d9](ae1a9d9))
* TypeVariableKind for just Integers
([#4118](#4118))
([c956be8](c956be8))
* Update error message when trying to load workspace as dependency
([#4393](#4393))
([d2585e7](d2585e7))


### Bug Fixes

* **acir:** Array dynamic flatten
([#4351](#4351))
([b2aaeab](b2aaeab))
* **acir:** Use types on dynamic arrays
([#4364](#4364))
([ba2c541](ba2c541))
* Add `follow_bindings` to follow `Type::Alias` links
([#4521](#4521))
([b94adb9](b94adb9))
* Add handling to `noir_wasm` for projects without dependencies
([#4344](#4344))
([4982251](4982251))
* Allow type aliases in main
([#4505](#4505))
([8a5359c](8a5359c))
* Ban Fields in for loop indices and bitwise ops
([#4376](#4376))
([601fd9a](601fd9a))
* Brillig range check with consistent bit size
([#4357](#4357))
([ea47d4a](ea47d4a))
* Build noir_codegen when publishing
([#4448](#4448))
([cb1ceee](cb1ceee))
* Consistent bit size for truncate
([#4370](#4370))
([dcd7a1e](dcd7a1e))
* Correct formatting for databus visibility types
([#4423](#4423))
([cd796de](cd796de))
* Correct invalid brillig codegen for `EmbeddedCurvePoint.add`
([#4382](#4382))
([5051ec4](5051ec4))
* **docs:** Update install versions
([#4396](#4396))
([b283637](b283637))
* **docs:** Update noirjs_app for 0.23
([#4378](#4378))
([f77f702](f77f702))
* Enforce matching types of binary ops in SSA
([#4391](#4391))
([70866ae](70866ae))
* Fix brillig slowdown when assigning arrays in loops
([#4472](#4472))
([2a53545](2a53545))
* **flake:** Stop flake.nix removing ignored-tests.txt
([#4455](#4455))
([ebaf05a](ebaf05a))
* Force src impl for == on slices
([#4507](#4507))
([1691274](1691274))
* Handling of gh deps in noir_wasm
([#4499](#4499))
([1d65370](1d65370))
* Iterative flattening pass
([#4492](#4492))
([33c1ef7](33c1ef7))
* Noir test incorrect reporting
(AztecProtocol/aztec-packages#4925)
([5f57ebb](5f57ebb))
* Only add `.nr` files to file manager
([#4380](#4380))
([8536c7c](8536c7c))
* Remove panic when generic array length is not resolvable
([#4408](#4408))
([00ab3db](00ab3db))
* Remove print from monomorphization pass
([#4417](#4417))
([27c66b3](27c66b3))
* **ssa:** Handle mergers of slices returned from calls
([#4496](#4496))
([f988d02](f988d02))
* Use correct type for numeric generics
([#4386](#4386))
([0a1d109](0a1d109))
* Variables from trait constraints being permanently bound over when
used within a trait impl
([#4450](#4450))
([ac60ef5](ac60ef5))


### Miscellaneous Chores

* Bump msrv to 1.73.0
([#4406](#4406))
([b5e5c30](b5e5c30))
* **ci:** Bump MSRV to 1.72.1 and enforce that ACVM can be published
using updated lockfile
([#4385](#4385))
([2fc95d2](2fc95d2))
* Move noir out of yarn-project
(AztecProtocol/aztec-packages#4479)
([78ef013](78ef013))
* Remove empty value from bounded vec
([#4431](#4431))
([b9384fb](b9384fb))
* Reserve `unchecked` keyword
([#4432](#4432))
([9544813](9544813))
</details>

<details><summary>0.41.0</summary>

## [0.41.0](v0.40.0...v0.41.0)
(2024-03-11)


### ⚠ BREAKING CHANGES

* Internal as a macro
(AztecProtocol/aztec-packages#4898)
* move noir out of yarn-project
(AztecProtocol/aztec-packages#4479)
* note type ids
(AztecProtocol/aztec-packages#4500)
* rename bigint_neg into bigint_sub
(AztecProtocol/aztec-packages#4420)
* Add expression width into acir
(AztecProtocol/aztec-packages#4014)
* init storage macro
(AztecProtocol/aztec-packages#4200)
* **acir:** Move `is_recursive` flag to be part of the circuit
definition (AztecProtocol/aztec-packages#4221)
* Sync commits from `aztec-packages`
([#4144](#4144))
* Breaking changes from aztec-packages
([#3955](#3955))
* Rename Arithmetic opcode to AssertZero
([#3840](#3840))
* Remove unused methods on ACIR opcodes
([#3841](#3841))
* Remove partial backend feature
([#3805](#3805))

### Features

* Add bit size to const opcode
(AztecProtocol/aztec-packages#4385)
([158c8ce](158c8ce))
* Add expression width into acir
(AztecProtocol/aztec-packages#4014)
([158c8ce](158c8ce))
* Add instrumentation for tracking variables in debugging
([#4122](#4122))
([c58d691](c58d691))
* Add poseidon2 opcode implementation for acvm/brillig, and Noir
([#4398](#4398))
([10e8292](10e8292))
* Add support for overriding expression width
([#4117](#4117))
([c8026d5](c8026d5))
* Added cast opcode and cast calldata
(AztecProtocol/aztec-packages#4423)
([78ef013](78ef013))
* Allow brillig to read arrays directly from memory
(AztecProtocol/aztec-packages#4460)
([158c8ce](158c8ce))
* Allow nested arrays and vectors in Brillig foreign calls
(AztecProtocol/aztec-packages#4478)
([158c8ce](158c8ce))
* Allow variables and stack trace inspection in the debugger
([#4184](#4184))
([bf263fc](bf263fc))
* **avm:** Back in avm context with macro - refactor context
(AztecProtocol/aztec-packages#4438)
([158c8ce](158c8ce))
* **aztec-nr:** Initial work for aztec public vm macro
(AztecProtocol/aztec-packages#4400)
([158c8ce](158c8ce))
* Aztec-packages
([#3754](#3754))
([c043265](c043265))
* Backpropagate constants in ACIR during optimization
([#3926](#3926))
([aad0da0](aad0da0))
* Breaking changes from aztec-packages
([#3955](#3955))
([5be049e](5be049e))
* Evaluation of dynamic assert messages
([#4101](#4101))
([c284e01](c284e01))
* Init storage macro
(AztecProtocol/aztec-packages#4200)
([158c8ce](158c8ce))
* Internal as a macro
(AztecProtocol/aztec-packages#4898)
([5f57ebb](5f57ebb))
* Note type ids
(AztecProtocol/aztec-packages#4500)
([78ef013](78ef013))
* Remove range constraints from witnesses which are constrained to be
constants ([#3928](#3928))
([afe9c7a](afe9c7a))
* Remove replacement of boolean range opcodes with `AssertZero` opcodes
([#4107](#4107))
([dac0e87](dac0e87))
* Speed up transformation of debug messages
([#3815](#3815))
([2a8af1e](2a8af1e))
* Sync `aztec-packages`
([#4011](#4011))
([fee2452](fee2452))
* Sync commits from `aztec-packages`
([#4068](#4068))
([7a8f3a3](7a8f3a3))
* Sync commits from `aztec-packages`
([#4144](#4144))
([0205d3b](0205d3b))
* Sync from aztec-packages
([#4483](#4483))
([fe8f277](fe8f277))


### Bug Fixes

* Deserialize odd length hex literals
([#3747](#3747))
([4000fb2](4000fb2))
* Noir test incorrect reporting
(AztecProtocol/aztec-packages#4925)
([5f57ebb](5f57ebb))
* Remove panic from `init_log_level` in `acvm_js`
([#4195](#4195))
([2e26530](2e26530))
* Return error rather instead of panicking on invalid circuit
([#3976](#3976))
([67201bf](67201bf))


### Miscellaneous Chores

* **acir:** Move `is_recursive` flag to be part of the circuit
definition (AztecProtocol/aztec-packages#4221)
([158c8ce](158c8ce))
* Move noir out of yarn-project
(AztecProtocol/aztec-packages#4479)
([78ef013](78ef013))
* Remove partial backend feature
([#3805](#3805))
([0383100](0383100))
* Remove unused methods on ACIR opcodes
([#3841](#3841))
([9e5d0e8](9e5d0e8))
* Rename Arithmetic opcode to AssertZero
([#3840](#3840))
([836f171](836f171))
* Rename bigint_neg into bigint_sub
(AztecProtocol/aztec-packages#4420)
([158c8ce](158c8ce))
</details>

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

---------

Co-authored-by: Savio <72797635+Savio-Sou@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Add HashMap collection
4 participants