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: CLAUDE.md
+4Lines changed: 4 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -63,6 +63,10 @@ When staging files, prefer `git add -u` or name specific files rather than `git
63
63
Never bulk-update lockfiles (`Cargo.lock`, `yarn.lock`). Use targeted updates only: `cargo update --precise <version> --package <name>` for Rust, and `yarn up <package>@<version>` in the relevant workspace for TypeScript. Bulk updates drag in unrelated transitive changes that make review impossible and frequently break reproducibility.
64
64
</lockfile_discipline>
65
65
66
+
<standard_contract_repin>
67
+
Never run `noir-projects/noir-contracts/bootstrap.sh pin-standard-build` on your own initiative. The pin exists so ordinary source or bytecode changes do NOT move the standard contracts' canonical addresses, and CI does not fail when the bytecode drifts. A re-pin is a deliberate redeploy decision for a human to make: if a change seems to need one, leave the pin, rebuild against it, and ask. See the comment on `pin-standard-build` for why re-pinning is breaking.
2. The note's nullifier was not in the nullifier tree
68
68
69
+
The `assert_local_note_was_*` helpers only work for the executing contract's own notes: this is because it is not possible for a contract to retrieve the app-siloed nullifier hiding secret key that corresponds to another contract. To prove facts about another contract's notes, use `assert_note_existed_by`, which supports notes of any contract (see [Prove note inclusion](#prove-note-inclusion)).
70
+
69
71
## Prove at a specific historical block
70
72
71
73
To prove against state at a specific past block (not just the anchor block):
@@ -83,13 +85,13 @@ Using `get_block_header_at` adds ~3k constraints to prove Archive tree membershi
Copy file name to clipboardExpand all lines: docs/docs-developers/docs/resources/migration_notes.md
+16Lines changed: 16 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -9,6 +9,22 @@ Aztec is in active development. Each version may introduce breaking changes that
9
9
10
10
## TBD
11
11
12
+
### [Aztec.nr] Standard contracts re-pinned at new addresses
13
+
14
+
The canonical `HandshakeRegistry` now protects handshake shared secrets from recipient forgery and includes the owner's address in its `PrivateMutable` initialization nullifiers, keeping the handshake state of accounts that share keys independent. All standard contracts have been re-pinned and move to new addresses. Handshakes established with a previous registry instance are not visible to the new one and must be re-established.
15
+
16
+
### [Aztec.nr] Note property selectors are typed and use packed-layout indices
17
+
18
+
The selectors in the generated `properties()` used the field's position in the note struct declaration, which pointed at the wrong packed field for any note with an earlier field packing to more than one `Field` (a `Point`, an array, a nested struct). Selector indices are now the field's offset in the note's packed representation, so `select`/`sort` criteria constrain the field they name.
19
+
20
+
Breaking changes:
21
+
22
+
-`PropertySelector<T>` carries the selected property's type. Hand-constructed literals need a type annotation, e.g. `let selector: PropertySelector<Field> = PropertySelector { index: 0, offset: 0, length: 32 };`.
23
+
-`select`/`sort` reject properties that pack to more than one `Field` at compile time.
24
+
-`select` takes its value typed as the property's type. Cast the value if a mixed-type comparison was intentional.
25
+
-`properties()` cannot be used with a custom `Packable` layout. Define property selectors manually for such notes.
26
+
- Every note field type must implement `Packable`, even when the note's own `Packable` is hand-written.
27
+
12
28
## 5.0.1
13
29
14
30
### [Aztec.nr] History note nullification helpers renamed and restricted to own-contract notes
Copy file name to clipboardExpand all lines: noir-projects/aztec-nr/CLAUDE.md
+30Lines changed: 30 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -34,6 +34,36 @@ Follow the Rust stdlib style roughly. See `PublicImmutable` in `state_vars/publi
34
34
-**Show practical patterns in examples.** Don't just show the API call — show it in context (e.g. inside a `#[external("public")]` function with realistic variable names).
35
35
-**Document cost for methods.** When relevant, note which AVM opcodes are invoked and how many times (e.g. "`SLOAD` is invoked a number of times equal to `T`'s packed length").
36
36
37
+
### Brevity and attitude
38
+
39
+
Write for a caller using the API, not for an implementor or an auditor. State what the item does and any restriction a caller must respect, plus the alternative to reach for — then stop. Leave out the internal mechanism and the security rationale behind a restriction: those belong in code comments messages or design docs, not the rustdoc. A reader who hits a restriction needs to know it exists and where to go next, not the argument for why it holds.
40
+
41
+
-**State the restriction, not the reason it's sound.** Say "this can only be used for X", not the multi-sentence explanation of what goes wrong otherwise.
42
+
-**Don't narrate the mechanism.** Key siloing, tree layouts, hash preimages, and similar internals are implementation detail; mention them only when a caller cannot use the API correctly without knowing (and then put them under `## Implementation Details`).
43
+
-**Point to the alternative instead of enumerating trade-offs.** A single "use `[other_fn]` for the other case" beats a paragraph weighing options.
44
+
45
+
Example — documenting a helper that only works on the executing contract's own notes:
46
+
47
+
```rust
48
+
// Too much: explains the key-siloing mechanism and the failure the guard prevents.
49
+
/// The note's nullifier is recomputed using the executing contract's app-siloed nullifier key
50
+
/// and then siloed with `confirmed_note.contract_address`. These only agree for the executing
51
+
/// contract's own notes; otherwise the non-inclusion proof passes unconditionally and wrongly
52
+
/// reports a nullified note as not nullified, so this asserts that
// Right: states the restriction and the alternative, nothing more.
56
+
/// ## Local notes only
57
+
///
58
+
/// This can only be used for notes of the executing contract. Use [`assert_note_existed_by`] to
59
+
/// prove existence of another contract's notes.
60
+
```
61
+
62
+
## Testing
63
+
64
+
-**No messages on assertions inside tests.** Write `assert_eq(actual, expected)` and `assert(cond)`, not `assert_eq(actual, expected, "values should match")`. The test's name and body already make clear what is being checked, so an assertion message is redundant noise. (Library code is the opposite: an `assert`/`panic` there must carry a message, since it explains a runtime failure to a contract developer.)
65
+
-`#[test(should_fail_with = "...")]` is not an assertion message and is encouraged. The string matches a substring of the expected failure, pinning down *which* error the failing case must produce so the test can't pass for the wrong reason.
66
+
37
67
## Logging
38
68
39
69
-**Always use the prefixed logging functions** from `crate::logging` (e.g. `logging::aztecnr_debug_log!`, `logging::aztecnr_debug_log_format!`). These automatically prepend `[aztec-nr] ` to all messages at compile time.
0 commit comments