Skip to content

fix: correct nonce/nullifier confusion in serialized zswap local state (PM-22025)#1128

Merged
m2ux merged 5 commits into
mainfrom
fix/PM-22025-nonce-nullifier-confusion-zswap-state
Apr 13, 2026
Merged

fix: correct nonce/nullifier confusion in serialized zswap local state (PM-22025)#1128
m2ux merged 5 commits into
mainfrom
fix/PM-22025-nonce-nullifier-confusion-zswap-state

Conversation

@m2ux

@m2ux m2ux commented Mar 30, 2026

Copy link
Copy Markdown
Contributor

Summary

Add regression tests verifying that serialized zswap local state uses the actual coin nonce (randomness), not the nullifier map key (spend identifier). Addresses Least Authority Q1 2026 Node DIFF audit Issue E (PM-22025). All 3 tests pass, clippy clean.

🎫 Ticket 📐 Engineering


Motivation

The Least Authority Q1 2026 Node DIFF audit (Issue E, Medium severity) identified a type-semantic confusion in EncodedZswapLocalState::from_zswap_state where coin_info.nonce was populated from the coin map key (a Nullifier/spend identifier) instead of the actual coin Nonce (randomness value). Both types are structurally identical newtypes around HashOutput([u8; 32]), making the confusion compile without error.

The code fix was applied in PR #895 (encoded_zswap_local_state.rs, Mar 11) and PR #1074 (fork/common/generate_intent.rs, Mar 25). This PR adds regression tests and a change file to prevent reintroduction and formally close the audit finding.


Changes

  • Regression tests — 3 unit tests in encoded_zswap_local_state.rs that construct a WalletState with distinct nonce (0xAA) and nullifier (0xBB) byte patterns, serialize via from_zswap_state, and assert the serialized nonce matches the coin value's Nonce — not the Nullifier map key
  • Change filechanges/changed/audit-nonce-nullifier-regression-tests.md documenting the audit remediation

📌 Submission Checklist

  • Changes are backward-compatible (or flagged if breaking)
  • Pull request description explains why the change is needed
  • Self-reviewed the diff
  • I have included a change file, or skipped for this reason: [reason]
  • If the changes introduce a new feature, I have bumped the node minor version
  • Update documentation (if relevant)
  • No new todos introduced

🔱 Fork Strategy

  • Node Runtime Update
  • Node Client Update
  • Other
  • N/A

🗹 TODO before merging

  • Ready for review

@m2ux m2ux self-assigned this Mar 30, 2026
@m2ux m2ux force-pushed the fix/PM-22025-nonce-nullifier-confusion-zswap-state branch from 2984da9 to 3095ff3 Compare March 30, 2026 19:48
@m2ux m2ux marked this pull request as ready for review March 31, 2026 00:08
@m2ux m2ux requested a review from a team as a code owner March 31, 2026 00:08
Comment thread util/toolkit/src/toolkit_js/encoded_zswap_local_state.rs Outdated
@CLAassistant

CLAassistant commented Apr 13, 2026

Copy link
Copy Markdown

CLA assistant check
All committers have signed the CLA.

@m2ux m2ux force-pushed the fix/PM-22025-nonce-nullifier-confusion-zswap-state branch from 39f9414 to 197611f Compare April 13, 2026 08:42
m2ux added 5 commits April 13, 2026 09:50
Signed-off-by: Mike Clay <mike.clay@shielded.io>
…erialization

Verify that EncodedZswapLocalState::from_zswap_state uses the coin
value's Nonce field, not the Nullifier map key, when serializing
coin info. Prevents reintroduction of the type-semantic confusion
identified in the Least Authority Q1 2026 Node DIFF audit (Issue E).

JIRA: PM-22025
Made-with: Cursor
Signed-off-by: Mike Clay <mike.clay@shielded.io>
Made-with: Cursor
Signed-off-by: Mike Clay <mike.clay@shielded.io>
Apply cargo fmt to test helper signature and use full Jira URL
in change file to satisfy CI checks.

Made-with: Cursor
Signed-off-by: Mike Clay <mike.clay@shielded.io>
The assert_eq already proves the nonce equals nonce_bytes (0xAA..),
making the assert_ne against nullifier_bytes (0xBB..) tautologically
true. Addresses review feedback from LGLO.

Signed-off-by: Mike Clay <mike.clay@shielded.io>
@m2ux m2ux force-pushed the fix/PM-22025-nonce-nullifier-confusion-zswap-state branch from 197611f to a86a8c6 Compare April 13, 2026 08:51
@m2ux m2ux enabled auto-merge April 13, 2026 08:55
@m2ux m2ux added this pull request to the merge queue Apr 13, 2026
Merged via the queue into main with commit 913a809 Apr 13, 2026
32 of 34 checks passed
@m2ux m2ux deleted the fix/PM-22025-nonce-nullifier-confusion-zswap-state branch April 13, 2026 10:16
m2ux added a commit that referenced this pull request Apr 23, 2026
…e (PM-22025) (#1128)

* chore: initialize branch for PM-22025


* test: add regression tests for nonce/nullifier distinction in zswap serialization

Verify that EncodedZswapLocalState::from_zswap_state uses the coin
value's Nonce field, not the Nullifier map key, when serializing
coin info. Prevents reintroduction of the type-semantic confusion
identified in the Least Authority Q1 2026 Node DIFF audit (Issue E).

JIRA: PM-22025
Made-with: Cursor

* chore: add change file for nonce/nullifier audit remediation (PM-22025)

Made-with: Cursor

* chore: fix formatting and JIRA link in change file

Apply cargo fmt to test helper signature and use full Jira URL
in change file to satisfy CI checks.

Made-with: Cursor

* chore: remove redundant assert_ne in nonce regression test

The assert_eq already proves the nonce equals nonce_bytes (0xAA..),
making the assert_ne against nullifier_bytes (0xBB..) tautologically
true. Addresses review feedback from LGLO.


---------


Signed-off-by: Mike Clay <mike.clay@shielded.io>
m2ux added a commit that referenced this pull request Apr 23, 2026
…e (PM-22025) (#1128)

* chore: initialize branch for PM-22025


* test: add regression tests for nonce/nullifier distinction in zswap serialization

Verify that EncodedZswapLocalState::from_zswap_state uses the coin
value's Nonce field, not the Nullifier map key, when serializing
coin info. Prevents reintroduction of the type-semantic confusion
identified in the Least Authority Q1 2026 Node DIFF audit (Issue E).

JIRA: PM-22025
Made-with: Cursor

* chore: add change file for nonce/nullifier audit remediation (PM-22025)

Made-with: Cursor

* chore: fix formatting and JIRA link in change file

Apply cargo fmt to test helper signature and use full Jira URL
in change file to satisfy CI checks.

Made-with: Cursor

* chore: remove redundant assert_ne in nonce regression test

The assert_eq already proves the nonce equals nonce_bytes (0xAA..),
making the assert_ne against nullifier_bytes (0xBB..) tautologically
true. Addresses review feedback from LGLO.


---------


Signed-off-by: Mike Clay <mike.clay@shielded.io>
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.

4 participants