Skip to content

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

Open
m2ux wants to merge 4 commits intomainfrom
fix/PM-22025-nonce-nullifier-confusion-zswap-state
Open

fix: correct nonce/nullifier confusion in serialized zswap local state (PM-22025)#1128
m2ux wants to merge 4 commits intomainfrom
fix/PM-22025-nonce-nullifier-confusion-zswap-state

Conversation

@m2ux
Copy link
Copy Markdown
Contributor

@m2ux m2ux commented Mar 30, 2026

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 added 2 commits March 30, 2026 22:56
…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
@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
Apply cargo fmt to test helper signature and use full Jira URL
in change file to satisfy CI checks.

Made-with: Cursor
);
assert_ne!(
encoded.outputs[0].coin_info.nonce, nullifier_bytes,
"serialized nonce must NOT be the Nullifier (map key)"
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is redundant. Previous check proves the value equals "serialized nonce must match the coin value's Nonce, not the map key Nullifier". Also "not equal" for nontrivial human readable English is likely to be true.

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.

2 participants