Skip to content

chore: combined uint audit#16030

Merged
suyash67 merged 3 commits into
merge-train/barretenbergfrom
sb/uint-combined
Jul 28, 2025
Merged

chore: combined uint audit#16030
suyash67 merged 3 commits into
merge-train/barretenbergfrom
sb/uint-combined

Conversation

@suyash67

Copy link
Copy Markdown
Contributor

All uint audit-related changes. Note we are going to remove uint module altogether, this PR/commit should serve as a fallback if we ever need to use uint in future.

suyash67 added 3 commits July 26, 2025 21:04
### 🧾 Audit Context

Audit of the `uint` module in stdlib, specifically the methods:
`operator>>`, `operator<<` and `ror` (bitwise operations).

### 🛠️ Changes Made

- All three methods were manually "slicing" a field element which was
very error-prone. I replaced it with `split_at` method (wrote a generic
method `split_at`[^1] that splits a field_t at a given bit index and
returns the lower and higher slices).
- Cleaned up and optimised `uint` constructor from `byte_array` and
`std::vector<bool_t>` (resolving old TODO)
- Added static assert on `width` so that we restrict `uint` to 8, 16,
32, and 64 bits only.

### ✅ Checklist

- [x] Audited all methods of the relevant module/class
- [x] Audited the interface of the module/class with other (relevant)
components
- [x] Documented existing functionality and any changes made (as per
Doxygen requirements)
- [x] Resolved and/or closed all issues/TODOs pertaining to the audited
files
- [x] Confirmed and documented any security or other issues found (if
applicable)
- [ ] Verified that tests cover all critical paths (and added tests if
necessary)
- [ ] Updated audit tracking for the files audited (check the start of
each file you audited)

### 📌 Notes for Reviewers

Please review the `split_at` function carefully, and check if we are
testing it thoroughly. We're soon going to remove the function
`slice(msb, lsb)` from field_t since we no longer need it (used only in
`logic` module). Instead, the new function `split_at` will replace the
use of `slice` in `logic` module:


https://github.com/AztecProtocol/aztec-packages/blob/6434f3193683748d31d94c787e87252234c6a6fd/barretenberg/cpp/src/barretenberg/stdlib/primitives/logic/logic.cpp#L99

will be changed to:

`field_pt a_slice = a.split_at(0, num_bits).second;`

Note: we are not going to merge any PRs that change anything in `field`
or `bigfield` as they're undergoing external audits at the moment. Thus,
this PR will be merged after the external audit of `field` (and its
fixes) are done.

[^1]: The existing `slice(msb, lsb)` method could be used but there were
three issues in doing so:
(a) found a
[bug](eb3f3ec)
in range-constraint on the `hi` limb in it,
(b) `slice(...)` returns three limbs: hi, mid and lo so it naturally
requires three range constraints. We only need two parts of a field
element.
(c) `slice(...)` assumes a 252-bit field element which results in
(unnecessary) costly range-constraints. We'd have to change the function
to accept `num_bits` as a parameter (or template parameter).
TLDR: `uint` arithmetic operators `+` and `-` had a coding error and as
a result, we weren't actually supporting lazy arithmetic over integers.
This PR simplifies the `uint` class to now allow any "unbounded" values.

#### The Issue 

In the current `uint` class, we allow "unbounded" values, for example, a
`uint32_ct` can contain a value > 32 bits. This was done to allow lazy
arithmetic before such values were "normalized". This is because a call
to `normalize()` is expensive: it decomposes the value in 12-bit slices
and range-constrains each slice.

In practice though, the addition and subtraction operator actually
didn't allow any overflow due to a coding error.
On adding two $\textsf{uint}x$ values $a$ and $b$ (where $x \in [8, 16,
32, 64]$), we currently do:


https://github.com/AztecProtocol/aztec-packages/blob/5c2c217a2f1b05ae226a16ee19a99079dbba8fec/barretenberg/cpp/src/barretenberg/stdlib/primitives/uint/arithmetic.cpp#L27-L47

Assume $a, b$ are both witnesses, the `create_balanced_add_gate` creates
the following constraint:

$$a + b = q \cdot \textcolor{grey}{2^x} + r$$

where the quotient $q$ and remainder $r$ are computed as:

$$q := \frac{(a \textsf{ mod } 2^x) + (b \textsf{ mod } 2^x)}{2^x},
\quad r := \left((a \textsf{ mod } 2^x) + (b \textsf{ mod } 2^x)\right)
\textsf{ mod } 2^x.$$

In other words, the quotient and remainder are computed from the
"truncated" values of $a$ and $b$ when it should have been from the
"unbounded" values. Effectively, this means we are not actually
supporting lazy arithmetic (i.e., arithmetic operations expect inputs to
be "normalized"). I wrote a test
[here](https://github.com/AztecProtocol/aztec-packages/blob/ace0afdb4fb773cfc50af92930ecb94993ab72a5/barretenberg/cpp/src/barretenberg/stdlib/primitives/uint/uint.test.cpp#L243-L271)
that fails when, ideally, it should have passed. This confirmed the
coding error.

#### Solution(s)

One way to fix this is to actually use `get_unbounded_value()` in place
of `get_value()` (on lines 27 and 28 in `operator+` above). But we never
really were using the benefits of lazy addition (because of this silly
error). So we decided its better to remove functionality related to
"unbounded" uint values.

Thus, we remove the `witness_status` member of the `uint` class as it
tracks if a `uint` needs to be "normalized". As a consequence, we now
need to "normalize" in every constructor where we weren't constraining
the accumulators (i.e., `byte_array` and `std::vector<bool_t>`).
Further, in `operator+` and `operator-` we normalize the result. Also,
removed the `get_unbounded_value()` as it isn't being used anywhere.
### 🧾 Audit Context

Remainder audit of `uint`.

### 🛠️ Changes Made

- Removed `at` function as it has a bug. The bug is explained
[here](https://github.com/AztecProtocol/aztec-packages/blob/3941e2f537a5257f4d19c0e018a73ab687151024/barretenberg/cpp/src/barretenberg/stdlib/primitives/uint/uint.cpp#L244-L249).
- Added assertions and minor comments.
- No circuit changes.

### ✅ Checklist

- [x] Audited all methods of the relevant module/class
- [x] Audited the interface of the module/class with other (relevant)
components
- [x] Documented existing functionality and any changes made (as per
Doxygen requirements)
- [x] Resolved and/or closed all issues/TODOs pertaining to the audited
files
- [x] Confirmed and documented any security or other issues found (if
applicable)
- [x] Verified that tests cover all critical paths (and added tests if
necessary)
- [x] Updated audit tracking for the files audited (check the start of
each file you audited)

### 📌 Notes for Reviewers

NA
@suyash67 suyash67 merged commit c18ef5e into merge-train/barretenberg Jul 28, 2025
4 checks passed
@suyash67 suyash67 deleted the sb/uint-combined branch July 28, 2025 10:54
github-merge-queue Bot pushed a commit that referenced this pull request Jul 30, 2025
See
[merge-train-readme.md](https://github.com/AztecProtocol/aztec-packages/blob/next/.github/workflows/merge-train-readme.md).

BEGIN_COMMIT_OVERRIDE
chore: remove `logic` operations from `uint` (#15975)
chore: Modify the `MergeVerifier` so that it gets the subtable
commitments as input and returns the commitment to the merged table
(#15949)
fix: delete tar generated by test-vk-havent-changed script (#15988)
chore: replace q_arith with q_3 in memory relation (#15953)
chore: simplify `uint` logic by removing `witness_status` (#15976)
Revert "chore: remove `logic` operations from `uint`" (#15997)
Revert "chore: simplify `uint` logic by removing `witness_status`"
(#16000)
feat: Add the last merged table to the public inputs of the hiding
circuit (#15829)
chore: combined `uint` audit (#16030)
chore: delete and ignore barretenberg/src/honk/keys/ (#16042)
fix: Fix tube proof construction (#16052)
feat: Link successive recursive Merge verifications (#16032)
chore: Package inputs to Merge verifier into a single struct (#16075)
END_COMMIT_OVERRIDE

---------

Co-authored-by: AztecBot <tech@aztecprotocol.com>
Co-authored-by: Suyash Bagad <suyash@aztecprotocol.com>
Co-authored-by: federicobarbacovi <171914500+federicobarbacovi@users.noreply.github.com>
Co-authored-by: Jonathan Hao <jonathan@aztec-labs.com>
Co-authored-by: ledwards2225 <98505400+ledwards2225@users.noreply.github.com>
Co-authored-by: sergei iakovenko <105737703+iakovenkos@users.noreply.github.com>
Co-authored-by: ludamad <adam.domurad@gmail.com>
Co-authored-by: Raju Krishnamoorthy <krishnamoorthy@gmail.com>
Co-authored-by: notnotraju <raju@aztec-labs.com>
Co-authored-by: Lucas Xia <lucasxia01@gmail.com>
Co-authored-by: Khashayar Barooti <khashayar@aztecprotocol.com>
Co-authored-by: Jean M <132435771+jeanmon@users.noreply.github.com>
Co-authored-by: Alex Gherghisan <alexghr@users.noreply.github.com>
Co-authored-by: Santiago Palladino <spalladino@users.noreply.github.com>
Co-authored-by: Santiago Palladino <santiago@aztec-labs.com>
Co-authored-by: ludamad <domuradical@gmail.com>
Co-authored-by: maramihali <mara@aztecprotocol.com>
Co-authored-by: Sarkoxed <75146596+Sarkoxed@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.

1 participant