From 09c3012e6f95a67e53ad68e75d9dcd2838a9367e Mon Sep 17 00:00:00 2001 From: James Zaki Date: Tue, 25 Feb 2025 18:13:35 +0000 Subject: [PATCH 1/2] Doc auto-change on save --- docs/docs/explainers/explainer-writing-noir.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/docs/explainers/explainer-writing-noir.md b/docs/docs/explainers/explainer-writing-noir.md index b4265a14dbf..b4d9f51e6b9 100644 --- a/docs/docs/explainers/explainer-writing-noir.md +++ b/docs/docs/explainers/explainer-writing-noir.md @@ -70,7 +70,7 @@ A few things to do when converting Rust code to Noir: - No early `return` in function. Use constrain via assertion instead - No passing by reference. Remove `&` operator to pass by value (copy) - No boolean operators (`&&`, `||`). Use bitwise operators (`&`, `|`) with boolean values -- No type `usize`. Use types `u8`, `u32`, `u64`, ... +- No type `usize`. Use types `u8`, `u32`, `u64`, ... - `main` return must be public, `pub` - No `const`, use `global` - Noir's LSP is your friend, so error message should be informative enough to resolve syntax issues. From 20f03b5b604988c57878805f2fb21a1ff23f63e7 Mon Sep 17 00:00:00 2001 From: James Zaki Date: Tue, 25 Feb 2025 18:15:39 +0000 Subject: [PATCH 2/2] Add note on no_predicates --- docs/docs/explainers/explainer-writing-noir.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/docs/docs/explainers/explainer-writing-noir.md b/docs/docs/explainers/explainer-writing-noir.md index b4d9f51e6b9..784d14a22d2 100644 --- a/docs/docs/explainers/explainer-writing-noir.md +++ b/docs/docs/explainers/explainer-writing-noir.md @@ -184,6 +184,18 @@ Use ` if is_unconstrained() { /`, to conditionally execute code if being called Unless you're well into the depth of gate optimization, this advanced section can be ignored. +### `#[no_predicates]` over for "pure" functions + +When conditional logic is compiled into gates, it is predicated with boolean expressions like X, where `X * V1() + (1-X) * V2()` is calculated. This returns `V1()` when `X` is true or `V2()` if `X` is false. + +If a function is guaranteed to never fail an assertion no matter the inputs, or roughly considered "pure", it can use the macro `#[no_predicates]`, telling the compiler to not add such predicates. This can beneficially be used in say hashing functions to reduce the gate count when they intuitively must be written/used inside an `if`. + +:::note +If a function may call other predicated functions, do not mark it with `#[no_predicates]`. +::: + +Having a `#[no_predicates]` function call a regular function severely breaks the intended representation, proof generation, and verification of the program. + ### Combine arithmetic operations A Noir program can be honed further by combining arithmetic operators in a way that makes the most of each constraint of the backend proving system. This is in scenarios where the backend might not be doing this perfectly.