You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/docs/aztec/writing_efficient_contracts.md
+15-12Lines changed: 15 additions & 12 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -37,6 +37,7 @@ Since proof generation is a significant local burden, being mindful of the gate-
37
37
An explanation of efficient use of Noir for circuits should be considered for each subsection under [writing efficient Noir](https://noir-lang.org/docs/explainers/explainer-writing-noir#writing-efficient-noir-for-performant-products) to avoid hitting local limits. The general theme is to use language features that favour the underlying primitives and representation of a circuit from code.
38
38
39
39
A couple of examples:
40
+
40
41
- Since the underlying cryptography uses an equation made of additions and multiplications, these are more efficient (wrt gate count) in Noir than say bit-shifting.
41
42
- Unconstrained functions by definition do not constrain their operations/output, so do not contribute to gate count. Using them carefully can bring in some savings, but the results must then be constrained so that proofs are meaningful for your application.
42
43
@@ -50,7 +51,7 @@ When private functions are called, the overhead of a "kernel circuit" is added e
50
51
51
52
#### Profiling using FlameGraph
52
53
53
-
Measuring the gate count across a private function can be seen at the end of the counter tutorial [here](../developers/tutorials/contract_tutorials/counter_contract#investigate-the-increment-function). Full profiling and flamegraph commands explained [here](../developers/guides/smart_contracts/profiling_transactions).
54
+
Measuring the gate count across a private function can be seen at the end of the counter tutorial [here](../developers/tutorials/contract_tutorials/counter_contract#investigate-the-increment-function). Full profiling and flamegraph commands explained [here](../developers/guides/smart_contracts/advanced/profiling_transactions).
54
55
55
56
### L2 Data costs
56
57
@@ -63,7 +64,6 @@ That is, what is stored in an L1 contract is simply a hash.
63
64
64
65
For data availability, blobs are utilized since data storage is often cheaper here than in contracts. Like other L2s such costs are factored into the L2 fee mechanisms. These limits can be seen and iterated on when a transaction is simulated/estimated.
65
66
66
-
67
67
## Examples for private functions (reducing gate count)
68
68
69
69
After the first section about generating a flamegraph for an Aztec function, each section shows an example of different optimisation techniques.
@@ -78,14 +78,14 @@ For example, the resulting flamegraph (as an .svg file) of a counter's increment
78
78
79
79
To get a sense of things, here is a table of gate counts for common operations:
80
80
81
-
Gates | Operation
82
-
----- | ----------
83
-
~75 | Hashing 3 fields with Poseidon2
84
-
3500 | Reading a value from a tree (public data tree, note hash tree, nullifier tree)
85
-
4000 | Reading a delayed public mutable read
86
-
X000 | Calculating sha256
87
-
X000 | Constrained encryption of a log of Y fields
88
-
X000 | Constrained encryption and tag a log of Y fields
|3500 | Reading a value from a tree (public data tree, note hash tree, nullifier tree)|
85
+
|4000 | Reading a delayed public mutable read|
86
+
|X000 | Calculating sha256|
87
+
|X000 | Constrained encryption of a log of Y fields|
88
+
|X000 | Constrained encryption and tag a log of Y fields|
89
89
90
90
### Optimization: use arithmetic instead of non-arithmetic operations
91
91
@@ -115,7 +115,6 @@ In the same vein bitwise `AND`/`OR`, and inequality relational operators (`>`, `
115
115
116
116
For example, use boolean equality effectively instead of `>=`:
117
117
118
-
119
118
```rust
120
119
{
121
120
#[private]
@@ -147,6 +146,7 @@ For example, use boolean equality effectively instead of `>=`:
147
146
```
148
147
149
148
So for a loop of 1000 iterations, 751 gates were saved by:
149
+
150
150
- Adding an equivalence check and a boolean assignment
151
151
- Replacing `>=` with a boolean equivalence check
152
152
@@ -161,9 +161,11 @@ Since private functions are circuits, their size must be known at compile time,
161
161
See [this example](https://github.com/noir-lang/noir-examples/blob/master/noir_by_example/loops/noir/src/main.nr#L11) for how to use loops when dynamic execution lengths (ie variable number of loops) is not possible.
162
162
163
163
### Optimization: considered use of `unconstrained` functions
164
+
164
165
#### Example - calculating square root
165
166
166
167
Consider the following example of an implementation of the `sqrt` function:
168
+
167
169
```rust
168
170
usedep::aztec::macros::aztec;
169
171
@@ -226,6 +228,7 @@ The two implementations after the contract differ in one being constrained vs un
226
228
Measuring the two, we find the `sqrt_inefficient` to require around 1500 extra gates compared to `sqrt_efficient`.
If a struct has many fields to be read, we can design an extra variable maintained as the hash of all values within it (like a checksum). When it comes to reading, we can now do an unconstrained read (incurring no read requests), and then check the hash of the result against that stored for the struct. This final check is thus only one read request rather than one per variable.
356
359
357
360
:::note Leverage unconstrained functions
358
-
When needing to make use of large private operations (eg private execution or many read requests), use of [unconstrained functions](https://noir-lang.org/docs/explainers/explainer-writing-noir#leverage-unconstrained-execution) wisely to reduce the gate count of private functions.
361
+
When needing to make use of large private operations (eg private execution or many read requests), use of [unconstrained functions](https://noir-lang.org/docs/explainers/explainer-writing-noir#leverage-unconstrained-execution) wisely to reduce the gate count of private functions.
0 commit comments