Skip to content

test: run remaining categories live and unify shielded-key fixtures#694

Open
0xisk wants to merge 10 commits into
mainfrom
test/live-harness-remaining-categories
Open

test: run remaining categories live and unify shielded-key fixtures#694
0xisk wants to merge 10 commits into
mainfrom
test/live-harness-remaining-categories

Conversation

@0xisk

@0xisk 0xisk commented Jul 17, 2026

Copy link
Copy Markdown
Member

Summary

Builds on #673 (the live-backend harness) to run the remaining contract categories on the live node, and consolidates the shared shielded-key test fixtures.

Blocked

Live coverage

  • token — the shielded-token specs (NativeShieldedToken, Core, Family, and the supply property spec) run backend-aware: node-resolvable recipients and per-run mint nonces on live, dry assertions preserved.
  • accessZOwnablePK runs live, binding its owner ids to pooled wallets so the negative "not the owner" checks stay honest on a real node.
  • The live runner drops the LIVE_READY allowlist: every src/<category> with tests runs live (opt-out via EXCLUDED_CATEGORIES, only legacy archive today), and --list reports the full set so CI stays in sync.

Fixture refactor

  • Collapse the three backend-aware shielded-key helpers (shieldedTestRecipient, shieldedTestParentKey, shieldedTestSigner) into one shieldedTestKey(alias = 'deployer') returning an EncodedRecipient.
  • Callers needing a bare coin public key read .left, typed EncodedCoinPublicKey from @midnight-ntwrk/compact-runtime (no hand-rolled { bytes: Uint8Array }).
  • All consumers migrated (token, access, multisig, forwarder, treasury). Full dry unit suite passes (1399 tests).

Types of changes

  • Bugfix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Documentation Update (if none of the other choices apply)

Closes #668 Closes #669 Closes #670 Closes #671 Closes #672

PR Checklist

  • I have read the Contributing Guide
  • I have added tests that prove my fix is effective or that my feature works.
  • I have added documentation for new methods or changes to existing method behavior.
  • CI Workflows Are Passing

Summary by CodeRabbit

  • New Features

    • Expanded live test coverage across multisig, token, access, security, crypto, and utility categories.
    • Added automatic discovery of live-ready test categories with support for explicit exclusions.
  • Bug Fixes

    • Improved live-backend token minting and burning tests using valid recipients and nonces.
    • Prevented unsupported witness and archive tests from running in live environments.
  • Documentation

    • Updated contribution guidance to reflect expanded live testing and automatic category discovery.

@coderabbitai

coderabbitai Bot commented Jul 17, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Walkthrough

The PR consolidates shielded test-key fixtures, expands automatic live-category discovery, excludes witness suites from live runs, and updates token, access, and multisig tests for backend-specific execution.

Changes

Live backend test expansion

Layer / File(s) Summary
Backend-aware shielded key fixture
contracts/test-utils/fixtures/shieldedKey.ts, contracts/test-utils/fixtures/test/shieldedKey.test.ts
shieldedTestKey resolves published coin keys from environment variables and falls back to deterministic synthetic keys, replacing separate recipient, parent, and signer helpers.
Live category discovery and exclusions
scripts/test-live.ts, contracts/vitest.config.ts, CONTRIBUTING.md
Live categories are discovered automatically, archive and witness suites remain excluded, and documentation describes the expanded coverage.
Backend-aware token execution
contracts/src/token/test/*
Token tests use live recipients and nonces, mint real coins before live burns, retain dry fabricated-coin paths, and skip supply fuzzing on live.
Access and multisig fixture migration
contracts/src/access/test/ZOwnablePK.test.ts, contracts/src/multisig/test/*
Access and multisig tests use shieldedTestKey aliases and left-arm key extraction without changing contract assertions.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Sequence Diagram(s)

sequenceDiagram
  participant LiveRunner
  participant TokenTests
  participant shieldedTestKey
  participant LiveBackend
  LiveRunner->>TokenTests: discover and execute live category
  TokenTests->>shieldedTestKey: resolve recipient and nonce inputs
  shieldedTestKey-->>TokenTests: return backend-aware key
  TokenTests->>LiveBackend: mint real coin
  LiveBackend-->>TokenTests: return minted coin
  TokenTests->>LiveBackend: burn minted coin
  LiveBackend-->>TokenTests: return burn result
Loading

Possibly related issues

  • #665 — Expands the live-backend harness rollout across the same test categories.
  • #693 — Concerns whether the native token supply property suite should run on the live backend.

Possibly related PRs

Suggested labels: enhancement

Suggested reviewers: andrew-fleming, pepebndc

Poem

A rabbit hops where live coins flow,
With keys resolved from envs below.
Dry paths rest while real coins shine,
Mint, burn, and test now align.
“Hop onward!” says the bunny bright.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed The PR updates live-category discovery, adds backend-aware token/access coverage, and unifies fixtures to support the live harness goals in #668#672.
Out of Scope Changes check ✅ Passed The multisig, forwarder, and fixture test updates support the shared shielded-key/live harness work and do not appear unrelated to the PR objectives.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately captures the two main changes: expanding live execution to remaining categories and consolidating shielded-key fixtures.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch test/live-harness-remaining-categories

Warning

Review ran into problems

🔥 Problems

Git: Failed to clone repository. Please run the @coderabbitai full review command to re-trigger a full review. If the issue persists, set path_filters to include or exclude specific files.


Comment @coderabbitai help to get the list of available commands.

@0xisk 0xisk self-assigned this Jul 17, 2026
@0xisk
0xisk force-pushed the test/multisig-live-harness branch from a45bda7 to 7f6e09e Compare July 17, 2026 16:14
Base automatically changed from test/multisig-live-harness to main July 18, 2026 03:52
Thread the token specs through the backend-aware harness so they run
under MIDNIGHT_BACKEND=live against a real node, not only the dry
simulator. Coin-flow assertions split into un-gated blocks (guards that
revert before any coin reaches Zswap) and backend-aware blocks:

* recipients resolve to the deployer wallet's own coin public key on
  live (a key the node can resolve as a mint / refund target) and to
  the synthetic test user on dry;
* mint nonces are random per coin on live, since the local node
  persists nullifiers across runs and a fixed nonce replays a spent
  coin (Custom error 103); dry keeps the seeded nonce for reproducible
  assertions.

Covers NativeShieldedToken, NativeShieldedTokenCore,
NativeShieldedTokenFamily, and the supply property spec.
@0xisk
0xisk force-pushed the test/live-harness-remaining-categories branch from a2cc06d to 63ba3df Compare July 20, 2026 08:42
0xisk added 4 commits July 20, 2026 11:00
ZOwnablePK derives its owner id from SHA256(ownPublicKey(), nonce), so
the spec needs the caller's own bare ZswapCoinPublicKey rather than an
Either recipient. Add a shieldedTestSignerPK(alias) fixture helper: on
live it returns the pooled wallet's own coin public key (published as
MIDNIGHT_<ALIAS>_COIN_PK), so the off-chain owner commitment matches the
on-chain one the node computes for that signer; on dry it is the
deterministic synthetic key the dry backend resolves .as(alias) to.

Retarget the ZOwnablePK owner/new-owner ids through the helper so the
spec runs on both backends.
Now that access, token, and security carry backend-aware specs (and
crypto / utils run their pure computation through a real deploy), drop
the LIVE_READY allowlist from the live runner: every src/<category>
with tests runs live, and a category that must not is an explicit
opt-out (EXCLUDED_CATEGORIES, only legacy archive today). `--list`
prints every live category, keeping the CI matrix in sync with one
source of truth.

Add a LIVE_EXCLUDE to the unit-live vitest project that also drops
test/witnesses/** — those specs assert on wit_* helpers directly with a
fabricated WitnessContext, so MIDNIGHT_BACKEND=live changes nothing and
running them would only burn a worker slot. The dry unit project still
covers them.
Replace the "multisig is the only live-ready category" note with the
current behavior: every src/<category> with tests runs live, there is
no separate live-ready allowlist, and a category is kept off live only
via an explicit EXCLUDED_CATEGORIES opt-out.
The three backend-aware key helpers (shieldedTestRecipient,
shieldedTestParentKey, shieldedTestSigner) shared one env-lookup body
and differed only on which wallet they read and whether they returned
the Either or its bare `.left`. Collapse them into a single
`shieldedTestKey(alias = 'deployer')` returning an EncodedRecipient:

* `shieldedTestKey()` — the deployer's key (send recipient / drain
  parent), the former shieldedTestRecipient / shieldedTestParentKey.
* `shieldedTestKey('SIGNER1')` — a named pooled signer, the former
  shieldedTestSigner.
* callers needing a bare coin public key read `.left`, typed
  EncodedCoinPublicKey from compact-runtime, not a hand-rolled
  `{ bytes: Uint8Array }`.

Migrate every consumer (token, access, multisig, forwarder, treasury).
The only behavioral change is on the dry backend: recipient / parent
synthetic keys now derive from the `deployer` alias rather than a
cosmetic label. No spec depends on those exact bytes; the full dry
unit suite passes (1399 tests).
@0xisk 0xisk changed the title test: run remaining categories on the live harness test: run remaining categories live and unify shielded-key fixtures Jul 20, 2026
@0xisk
0xisk force-pushed the test/live-harness-remaining-categories branch from 63ba3df to acc6cde Compare July 20, 2026 09:26
@0xisk
0xisk marked this pull request as ready for review July 20, 2026 09:27
@0xisk
0xisk requested review from a team as code owners July 20, 2026 09:27
@0xisk
0xisk requested a review from andrew-fleming July 20, 2026 09:27

@coderabbitai coderabbitai Bot left a comment

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.

Actionable comments posted: 2

🧹 Nitpick comments (1)
contracts/test-utils/fixtures/shieldedKey.ts (1)

26-27: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

coinPkEnvVar only uppercases the 'deployer' alias.

For any other alias, the raw string is interpolated verbatim: coinPkEnvVar('signer1')MIDNIGHT_signer1_COIN_PK (won't match the harness-published MIDNIGHT_SIGNER1_COIN_PK), and even coinPkEnvVar('Deployer') misses the === 'deployer' check and produces MIDNIGHT_Deployer_COIN_PK. Since shieldedTestKey falls back to the dry synthetic key whenever the env lookup misses, a caller alias with unexpected casing silently gets a dry key on the live backend instead of erroring — hard to debug.

Uppercasing uniformly removes the special case and the asymmetry:

🔧 Proposed fix
-const coinPkEnvVar = (alias: string): string =>
-  `MIDNIGHT_${alias === 'deployer' ? 'DEPLOYER' : alias}_COIN_PK`;
+const coinPkEnvVar = (alias: string): string =>
+  `MIDNIGHT_${alias.toUpperCase()}_COIN_PK`;
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@contracts/test-utils/fixtures/shieldedKey.ts` around lines 26 - 27, Update
coinPkEnvVar to uppercase every alias uniformly when constructing the
MIDNIGHT_*_COIN_PK environment-variable name, removing the special-case deployer
branch. Preserve the existing prefix and suffix so aliases such as signer1 and
Deployer resolve to their uppercase harness-published keys.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@contracts/src/token/test/NativeShieldedToken.test.ts`:
- Around line 295-315: Gate the live _burnFromSelf tests as skipped, todo, or
expected-failure until they use a contract-held coin and recover its real
mt_index from ledger events. Apply this to the two tests in
contracts/src/token/test/NativeShieldedToken.test.ts lines 295-315, and the
corresponding live _burnFromSelf tests in
contracts/src/token/test/NativeShieldedTokenCore.test.ts lines 348-388 and
contracts/src/token/test/NativeShieldedTokenFamily.test.ts lines 291-331; no
other test behavior requires modification.

In `@scripts/test-live.ts`:
- Around line 334-340: Update the argument validation around liveCategories,
scoped, and categories to fail fast when the first argument looks like a
category name but is not an active live category, including excluded archive and
unknown category names. Report the invalid category before invoking expensive
setup such as compileVerified, env-up, or the harness, while preserving
filename-filter handling for valid category arguments and the existing
no-argument behavior.

---

Nitpick comments:
In `@contracts/test-utils/fixtures/shieldedKey.ts`:
- Around line 26-27: Update coinPkEnvVar to uppercase every alias uniformly when
constructing the MIDNIGHT_*_COIN_PK environment-variable name, removing the
special-case deployer branch. Preserve the existing prefix and suffix so aliases
such as signer1 and Deployer resolve to their uppercase harness-published keys.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: c5ee178b-fd8c-4cba-9e09-96b14c400325

📥 Commits

Reviewing files that changed from the base of the PR and between dd88196 and acc6cde.

📒 Files selected for processing (18)
  • CONTRIBUTING.md
  • contracts/src/access/test/ZOwnablePK.test.ts
  • contracts/src/multisig/test/Forwarder.test.ts
  • contracts/src/multisig/test/ForwarderPrivate.test.ts
  • contracts/src/multisig/test/ShieldedMultiSig.test.ts
  • contracts/src/multisig/test/ShieldedMultiSigV3.test.ts
  • contracts/src/multisig/test/ShieldedTreasury.test.ts
  • contracts/src/multisig/test/ShieldedTreasuryStateless.test.ts
  • contracts/src/multisig/test/presets/ForwarderPrivate.test.ts
  • contracts/src/multisig/test/presets/ForwarderShielded.test.ts
  • contracts/src/token/test/NativeShieldedToken.test.ts
  • contracts/src/token/test/NativeShieldedTokenCore.test.ts
  • contracts/src/token/test/NativeShieldedTokenFamily.test.ts
  • contracts/src/token/test/extensions/NativeShieldedTokenSupply.property.test.ts
  • contracts/test-utils/fixtures/shieldedKey.ts
  • contracts/test-utils/fixtures/test/shieldedKey.test.ts
  • contracts/vitest.config.ts
  • scripts/test-live.ts

Comment thread contracts/src/token/test/NativeShieldedToken.test.ts Outdated
Comment thread scripts/test-live.ts
0xisk and others added 5 commits July 20, 2026 12:22
The live `_burnFromSelf` happy-path blocks mint to the deployer wallet
(not the contract) and spend with a placeholder `mt_index: 0n`, so under
`runIf(isLiveBackend())` they revert deterministically against a real
node.

Mark them `describe.skip` until the coin is minted to the contract and
its real `mt_index` is recovered from the zswap ledger-events stream.
The dry fabricated-coin coverage is unchanged.
A first positional arg that is not an active live category — an excluded
one like `archive`, or a typo — silently degraded into a full-suite file
filter: the run attempted every category with the bad name as a vitest
filter, contrary to the documented contract (first arg names the
category) and only discovered after the expensive compile / env-up /
harness setup.

Fail fast with the valid set before that setup.
`coinPkEnv` (harness publisher) and the inlined `coinPkEnvVar`
(`shieldedKey` reader) both special-cased only `deployer`, interpolating
any other-cased alias verbatim. A `signer1` (or `Deployer`) alias would
publish and look up different env-var names, silently resolving a live
alias to a dry synthetic key.

Uppercase uniformly in both so publication and lookup always agree; keep
the two mappings in lockstep.
@0xisk 0xisk mentioned this pull request Jul 21, 2026
6 tasks
@andrew-fleming andrew-fleming added the blocked Issues blocked on other issues. label Jul 22, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

blocked Issues blocked on other issues.

Projects

None yet

2 participants