test: live-backend harness for the contract suite (core + multisig)#673
Conversation
|
Important Review skippedAuto incremental reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
WalkthroughThis PR migrates repository workflows from ChangesRepository build and test workflows
Multisig contracts, simulators, and tests
Live backend harness
Estimated code review effort: 5 (Critical) | ~120 minutes Possibly related issues
Possibly related PRs
Suggested labels: Suggested reviewers: Sequence Diagram(s)sequenceDiagram
participant LiveSetup
participant WalletPool
participant LiveSimulatorBackend
participant LocalNode
LiveSetup->>WalletPool: build and fund worker wallets
WalletPool->>LiveSimulatorBackend: register wallet aliases
LiveSimulatorBackend->>LocalNode: compile and deploy artifact
LocalNode-->>LiveSimulatorBackend: deployed contract address
LiveSimulatorBackend-->>LiveSetup: live simulator context
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 7
🧹 Nitpick comments (2)
contracts/vitest.config.ts (2)
43-52: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winDuplicate
MAX_LIVE_WORKERSconstant.
WalletPool.tsalready exportsMAX_LIVE_WORKERS = 3(used bylive.setup.tsto boundVITEST_POOL_ID). Redefining the same cap here risks the two drifting apart silently.♻️ Import the shared constant instead of redefining it
-const MAX_LIVE_WORKERS = 3; +import { MAX_LIVE_WORKERS } from './test-utils/harness/WalletPool.js';🤖 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/vitest.config.ts` around lines 43 - 52, Remove the local MAX_LIVE_WORKERS declaration in vitest.config.ts and import the shared exported MAX_LIVE_WORKERS from WalletPool.ts. Keep the existing liveWorkers calculation unchanged so it continues using the shared cap.
135-146: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win
harness-livelacks thegroupOrderisolation given tounit-live.Per the comment on
unit-live(lines 113-116), Vitest rejects a multi-project run where two projects share a group but differ inmaxWorkers.harness-live'sfileParallelism: falseimplicitly forcesmaxWorkers: 1, differing fromunit/integration/harness's defaults in the same (unset) group — the same hazardunit-livewas givengroupOrder: 1to avoid. Only a problem if all projects are ever run together without--project, but worth closing for consistency.♻️ Give harness-live its own group
test: { ...NODE, ...LIVE_SEQUENTIAL, name: 'harness-live', include: ['test-utils/**/*.test.ts'], globalSetup: ['./test-utils/harness/live.globalSetup.ts'], + sequence: { ...LIVE_SEQUENTIAL.sequence, groupOrder: 2 }, },🤖 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/vitest.config.ts` around lines 135 - 146, Add the same isolated groupOrder configuration used by unit-live to the harness-live project entry. Keep its existing LIVE_SEQUENTIAL, project name, include pattern, and globalSetup unchanged, ensuring harness-live is separated from harness and other projects with different worker settings.
🤖 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/multisig/test/ShieldedTreasury.test.ts`:
- Around line 30-33: Correct the comment above Z_RECIPIENT to state that it is
assigned in beforeAll, matching the initialization at beforeAll and the nearby
“resolve it once after the first deploy” comment. Preserve the existing
explanation of live wallet synchronization and dry-run behavior.
In `@contracts/src/multisig/test/simulators/ShieldedProposalMultisigSimulator.ts`:
- Around line 142-149: Update getReceivedMinusSent to await
getReceivedTotal(color) before invoking getSentTotal(color), ensuring the two
impure simulator queries run sequentially; preserve the existing subtraction and
returned bigint result.
In `@contracts/test-utils/harness/FundedWallet.ts`:
- Around line 92-116: Wrap provider startup, funding, synchronization, and
balanceTx setup in a try/catch within the FundedWallet initialization flow, and
call provider.stop() when any step fails before rethrowing the original error.
Ensure cleanup also covers failures from start, waitForFunds, and syncWallet,
while preserving the successful return of the FundedWallet instance.
In `@contracts/test-utils/harness/network.ts`:
- Around line 9-13: Replace the direct Number conversions in PORTS with shared
validation that accepts only integer port values from 1 through 65535, rejecting
empty, malformed, fractional, zero, and out-of-range overrides. When validation
fails, throw an error identifying the responsible environment-variable name,
while preserving the existing defaults for unset variables.
In `@contracts/test-utils/harness/test/network.test.ts`:
- Around line 11-18: Update the “should default to the local stack ports” test
in the PORTS describe block to isolate it from environment overrides: save and
clear all supported MIDNIGHT_*_PORT variables before dynamically importing
network.js, assert the imported PORTS defaults, and restore the original
environment values afterward even if the assertion fails.
In `@contracts/test-utils/harness/WalletPool.ts`:
- Around line 104-114: Update WalletPool.ensureReady to build wallets
sequentially instead of using Promise.all over Object.entries(this.seeds).
Preserve the existing per-wallet setup—await buildWallet, set coinPkEnv(alias),
and store the wallet in this.wallets—while ensuring each builder completes
before starting the next so shared-deployer funding cannot race.
In `@turbo.json`:
- Around line 60-69: Update the compile task’s dependsOn list in turbo.json to
include compile:archive, preserving the existing compile dependencies so
aggregate compile and its dependent test tasks rebuild archive artifacts.
---
Nitpick comments:
In `@contracts/vitest.config.ts`:
- Around line 43-52: Remove the local MAX_LIVE_WORKERS declaration in
vitest.config.ts and import the shared exported MAX_LIVE_WORKERS from
WalletPool.ts. Keep the existing liveWorkers calculation unchanged so it
continues using the shared cap.
- Around line 135-146: Add the same isolated groupOrder configuration used by
unit-live to the harness-live project entry. Keep its existing LIVE_SEQUENTIAL,
project name, include pattern, and globalSetup unchanged, ensuring harness-live
is separated from harness and other projects with different worker settings.
🪄 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: 9c3d96c3-a237-41e7-957c-97139d2cf02b
⛔ Files ignored due to path filters (1)
yarn.lockis excluded by!**/yarn.lock,!**/*.lock
📒 Files selected for processing (84)
.github/ISSUE_TEMPLATE/01_bug_report.yml.github/workflows/checks.yml.github/workflows/test.ymlCHANGELOG.mdCONTRIBUTING.mdcontracts/package.jsoncontracts/src/access/test/AccessControl.test.tscontracts/src/access/test/Ownable.test.tscontracts/src/access/test/ZOwnablePK.test.tscontracts/src/multisig/presets/NativeShieldedTokenMultisig.compactcontracts/src/multisig/presets/ShieldedProposalMultisig.compactcontracts/src/multisig/presets/ShieldedStatelessMultisig.compactcontracts/src/multisig/test/EmptyWitnesses.tscontracts/src/multisig/test/Forwarder.test.tscontracts/src/multisig/test/ForwarderPrivate.test.tscontracts/src/multisig/test/NativeShieldedTokenMultisig.test.tscontracts/src/multisig/test/ProposalManager.test.tscontracts/src/multisig/test/ShieldedMultiSig.test.tscontracts/src/multisig/test/ShieldedProposalMultisig.test.tscontracts/src/multisig/test/ShieldedStatelessMultisig.test.tscontracts/src/multisig/test/ShieldedTreasury.test.tscontracts/src/multisig/test/ShieldedTreasuryStateless.test.tscontracts/src/multisig/test/Signer.test.tscontracts/src/multisig/test/SignerManager.test.tscontracts/src/multisig/test/presets/ForwarderPrivate.test.tscontracts/src/multisig/test/presets/ForwarderShielded.test.tscontracts/src/multisig/test/presets/ForwarderUnshielded.test.tscontracts/src/multisig/test/simulators/MockShieldedTreasuryStatelessSimulator.tscontracts/src/multisig/test/simulators/NativeShieldedTokenMultisigSimulator.tscontracts/src/multisig/test/simulators/ProposalManagerSimulator.tscontracts/src/multisig/test/simulators/ShieldedProposalMultisigSimulator.tscontracts/src/multisig/test/simulators/ShieldedStatelessMultisigSimulator.tscontracts/src/multisig/test/simulators/ShieldedTreasurySimulator.tscontracts/src/multisig/test/simulators/SignerManagerSimulator.tscontracts/src/multisig/test/simulators/SignerSimulator.tscontracts/src/multisig/test/witnesses/ProposalManagerWitnesses.tscontracts/src/multisig/test/witnesses/ShieldedMultiSigV2Witnesses.tscontracts/src/multisig/test/witnesses/ShieldedMultiSigV3Witnesses.tscontracts/src/multisig/test/witnesses/ShieldedMultiSigWitnesses.tscontracts/src/multisig/test/witnesses/ShieldedTreasuryWitnesses.tscontracts/src/multisig/test/witnesses/SignerManagerWitnesses.tscontracts/src/multisig/test/witnesses/SignerWitnesses.tscontracts/src/multisig/test/witnesses/UnshieldedTreasuryWitnesses.tscontracts/src/token/test/FungibleToken.test.tscontracts/src/token/test/MultiToken.test.tscontracts/src/token/test/NativeShieldedToken.test.tscontracts/src/token/test/NativeShieldedTokenCore.test.tscontracts/src/token/test/NativeShieldedTokenFamily.test.tscontracts/src/token/test/nonFungibleToken.test.tscontracts/src/utils/test/utils.test.tscontracts/test-utils/fixtures/address.tscontracts/test-utils/fixtures/nativeShieldedToken.tscontracts/test-utils/fixtures/shieldedKey.tscontracts/test-utils/fixtures/test/address.test.tscontracts/test-utils/fixtures/test/nativeShieldedToken.test.tscontracts/test-utils/fixtures/test/shieldedKey.test.tscontracts/test-utils/fixtures/test/zswap.test.tscontracts/test-utils/fixtures/zswap.tscontracts/test-utils/harness/FundedWallet.tscontracts/test-utils/harness/LiveSimulatorBackend.tscontracts/test-utils/harness/NativeShieldedTokenTracker.tscontracts/test-utils/harness/WalletPool.tscontracts/test-utils/harness/dust.tscontracts/test-utils/harness/funding.tscontracts/test-utils/harness/ledgerEvents.tscontracts/test-utils/harness/live.globalSetup.tscontracts/test-utils/harness/live.setup.tscontracts/test-utils/harness/liveProgressReporter.tscontracts/test-utils/harness/network.tscontracts/test-utils/harness/test/FundedWallet.test.tscontracts/test-utils/harness/test/LiveSimulatorBackend.test.tscontracts/test-utils/harness/test/NativeShieldedTokenTracker.test.tscontracts/test-utils/harness/test/WalletPool.test.tscontracts/test-utils/harness/test/dust.test.tscontracts/test-utils/harness/test/liveGlobalSetup.test.tscontracts/test-utils/harness/test/network.test.tscontracts/vitest.config.tscontracts/vitest.integration.config.tscontracts/vitest.live.config.tslocal-env.ymlpackage.jsonscripts/keyIntegrity.tsscripts/test-live.tsturbo.json
💤 Files with no reviewable changes (11)
- contracts/vitest.live.config.ts
- contracts/src/multisig/test/witnesses/SignerManagerWitnesses.ts
- contracts/src/multisig/test/witnesses/ShieldedMultiSigV2Witnesses.ts
- contracts/src/multisig/test/witnesses/SignerWitnesses.ts
- contracts/src/multisig/test/witnesses/ShieldedTreasuryWitnesses.ts
- contracts/src/multisig/test/witnesses/ShieldedMultiSigV3Witnesses.ts
- contracts/src/multisig/test/witnesses/ProposalManagerWitnesses.ts
- contracts/src/multisig/test/witnesses/UnshieldedTreasuryWitnesses.ts
- contracts/vitest.integration.config.ts
- contracts/src/multisig/test/witnesses/ShieldedMultiSigWitnesses.ts
- contracts/src/multisig/test/ShieldedMultiSig.test.ts
62fc4e8 to
0ae9c1c
Compare
|
@andrew-fleming added docs on how to run live test per specific test file. 2bdab60 |
CI for the live suite:
|
andrew-fleming
left a comment
There was a problem hiding this comment.
Excellent work, @0xisk! This is a partial review, but I left some comments and questions
Also, make env-up is not portable across Docker Compose versions (I can't highlight the makefile here). yarn test:live aborts during startup on my machine. My quick fix to get it working:
docker compose -f $(COMPOSE_FILE) up -d
docker compose -f $(COMPOSE_FILE) up -d --wait node indexer| describe.skipIf(isLiveBackend())( | ||
| '_send — change coin is spendable, via Zswap I/O (dry only, no double spend)', | ||
| () => { |
There was a problem hiding this comment.
followup: Why not just insert dry as a description in the describe block with isLiveBackend and have the dry-only tests inside of it blocks?
There was a problem hiding this comment.
Could you elaborate more? Because I this is already in place here: ShieldedTreasuryStateless.test.ts uses describe.skipIf(isLiveBackend())('… (dry only)') paired with describe.runIf(isLiveBackend())('… on live'), with the dry/live split right in the describe labels.
The live CI workflow (`live.yml`) and its "Live tests in CI" CONTRIBUTING subsection are too large and complex to review alongside the harness. Per review, remove them here and land them in a separate PR stacked on this branch. Refs: #673
Companion to the previous commit: the "Live tests in CI" subsection documented and linked `live.yml`, which moves to the follow-up PR. Refs: #673
Compiling the archive module as part of the full `compact` task fails locally (per review). Archive is excluded from the full compile on `main` too. Keep the `compact:archive` task for targeted runs, but drop it from the aggregate `dependsOn`. Refs: #673
`docker compose up -d --wait` waits on every service, including proof-server, which has no healthcheck. That is not portable across Docker Compose versions and aborts `yarn test:live` on some setups (reported in review). Start all services, then wait only on node and indexer, which expose healthchecks. Refs: #673
|
Fixed the |
The shielded preset rename (`ShieldedMultiSig*` to capability-based names) is a user-facing contract change unrelated to the test harness. Per review, revert it here so this PR keeps the presets under their existing names; the rename lands as its own stacked PR with a changelog entry. Harness-only content changes are preserved (e.g. the block-limit circuit trim in ShieldedMultiSig.compact). Refs: #673
Per review, enable Corepack once as a prerequisite instead of prefixing every command with `corepack`. CI already runs `corepack enable`, so plain `yarn` resolves to the version pinned in package.json. * CONTRIBUTING: document the one-time `corepack enable`; drop the prefix from every command * scripts/test-live.ts, keyIntegrity.ts, live.globalSetup.ts: invoke and print plain `yarn` Refs: #673
The live runner already scopes to a category via a positional arg (`test:live <category> [filter]`), and CI invokes it that way (`yarn test:live "$CATEGORY"`). Drop the per-category `test:live:multisig` script and document the argument form instead, so local usage matches CI and the script list does not grow one entry per category. Refs: #673
Round 2 reset the shared node once, then re-ran all failed files with a single worker. That removes parallel collisions but not sequential state pollution: an earlier round-2 file can dirty the node (e.g. leave a spent coin -> "Custom error: 103") and fail a later one, misclassifying a flake as REAL. Reset the node before each failed file so every one runs alone on a fresh node, matching the "passes in isolation" intent. Round 2 only re-runs the failed files, so the extra resets are cheap. Refs: #673
andrew-fleming
left a comment
There was a problem hiding this comment.
Looking good, @0xisk! Thank you for moving out the unrelated changes. I left some comments and questions
Per review, wrap the happy-path burn tests (real spends, dry-only for
now) in a single `describe.skipIf(isLiveBackend())('happy path (dry
only)')` instead of tagging each with `it.skipIf`, matching the
describe-based split already used in ShieldedTreasuryStateless. The
backend-agnostic reject tests stay as direct children; mint keeps its
lone skipIf (a single test needs no wrapper).
Refs: #673
The preset dropped getProposalRecipient/Amount/Color and getReceivedMinusSent to fit the deploy block limit. The preset simulator re-added them as methods that read like circuit calls but only derived the values, which is misleading. Remove them and read the fields directly off getProposal and the received/sent totals the preset does expose. Refs: #673
Extend the tracker tests beyond the dry surface: resolve a wallet- and a contract-owned coin to its mt_index, the anchor-block re-read, the not-found failure, and the process-wide singleton. Only the indexer event stream is mocked; the commitment math runs for real, so a resolve proves the tracker computes the commitment the indexer would emit. Refs: #673
The port() guard's promise (an empty, non-numeric, or out-of-range override throws at load time, naming the env var) had no test. Add the three cases. Refs: #673
sort() hid the build order, so the test could not tell serial from concurrent building. Assert the exact order and a max concurrency of one via a counting builder. Also fix the class doc that wrongly said "concurrently"; the builder is serial on purpose (it funds empty signers from the shared deployer). Refs: #673
Two operational gaps in the same workflow, batched because the hunks share live.yml: * Artifact split: the JSON verdict reports are tiny and useful on green runs too (flaky trends), so they now upload on every run as live-reports-<category>. The service/worker logs, which can reach hundreds of MB after a multi-hour run, stay failure-only as live-logs-<category>. * Nightly visibility: a failed scheduled run only emails the workflow author. A report-nightly job now mirrors the state into a live-nightly tracking issue: opened on first failure, commented on repeats, closed automatically on the next green run. A suite skipped because the plan job died counts as a failure; a cancelled run reports nothing.
Document the per-job verdict summaries, the always-uploaded live-reports-<category> artifact, and the live-nightly tracking issue.
Nothing has invoked `turbo run test:live` (or the contracts test:live script it wrapped) since the unified runner replaced the root script in f751932. Keeping them left a second, guard-less entry point that skipped the stack reset, lock, and flake verdict. The runner is now the single way to run live tests.
Record the design decision in the runner header: turbo models a DAG of stateless, cacheable tasks, while a live run needs stateful orchestration (two-round flake verdict, docker lifecycle against one shared node, ZK-key self-heal, infra-vs-test exit codes). Turbo still handles the DAG-shaped steps (compile, harness smoke) inside the run.
The harness PR bundled a `compact`->`compile` and `fmt-and-lint`->`check` script rename that is unrelated to the test harness. Per review, back it out so this PR stays scoped to the harness. The rename will land as its own PR with a changelog entry. * package.json / contracts/package.json / turbo.json: restore the `compact:*` and `fmt-and-lint*` names, keeping every harness script, turbo task, and dependency * bug_report.yml / checks.yml / test.yml: reverted to main * scripts/test-live.ts, scripts/keyIntegrity.ts: invoke `yarn compact` again
Co-authored-by: Andrew Fleming <fleming-andrew@protonmail.com> Signed-off-by: 0xisk <0xisk@proton.me>
The live CI workflow (`live.yml`) and its "Live tests in CI" CONTRIBUTING subsection are too large and complex to review alongside the harness. Per review, remove them here and land them in a separate PR stacked on this branch. Refs: #673
Companion to the previous commit: the "Live tests in CI" subsection documented and linked `live.yml`, which moves to the follow-up PR. Refs: #673
Compiling the archive module as part of the full `compact` task fails locally (per review). Archive is excluded from the full compile on `main` too. Keep the `compact:archive` task for targeted runs, but drop it from the aggregate `dependsOn`. Refs: #673
`docker compose up -d --wait` waits on every service, including proof-server, which has no healthcheck. That is not portable across Docker Compose versions and aborts `yarn test:live` on some setups (reported in review). Start all services, then wait only on node and indexer, which expose healthchecks. Refs: #673
The shielded preset rename (`ShieldedMultiSig*` to capability-based names) is a user-facing contract change unrelated to the test harness. Per review, revert it here so this PR keeps the presets under their existing names; the rename lands as its own stacked PR with a changelog entry. Harness-only content changes are preserved (e.g. the block-limit circuit trim in ShieldedMultiSig.compact). Refs: #673
Per review, enable Corepack once as a prerequisite instead of prefixing every command with `corepack`. CI already runs `corepack enable`, so plain `yarn` resolves to the version pinned in package.json. * CONTRIBUTING: document the one-time `corepack enable`; drop the prefix from every command * scripts/test-live.ts, keyIntegrity.ts, live.globalSetup.ts: invoke and print plain `yarn` Refs: #673
The live runner already scopes to a category via a positional arg (`test:live <category> [filter]`), and CI invokes it that way (`yarn test:live "$CATEGORY"`). Drop the per-category `test:live:multisig` script and document the argument form instead, so local usage matches CI and the script list does not grow one entry per category. Refs: #673
Round 2 reset the shared node once, then re-ran all failed files with a single worker. That removes parallel collisions but not sequential state pollution: an earlier round-2 file can dirty the node (e.g. leave a spent coin -> "Custom error: 103") and fail a later one, misclassifying a flake as REAL. Reset the node before each failed file so every one runs alone on a fresh node, matching the "passes in isolation" intent. Round 2 only re-runs the failed files, so the extra resets are cheap. Refs: #673
Per review, wrap the happy-path burn tests (real spends, dry-only for
now) in a single `describe.skipIf(isLiveBackend())('happy path (dry
only)')` instead of tagging each with `it.skipIf`, matching the
describe-based split already used in ShieldedTreasuryStateless. The
backend-agnostic reject tests stay as direct children; mint keeps its
lone skipIf (a single test needs no wrapper).
Refs: #673
The preset dropped getProposalRecipient/Amount/Color and getReceivedMinusSent to fit the deploy block limit. The preset simulator re-added them as methods that read like circuit calls but only derived the values, which is misleading. Remove them and read the fields directly off getProposal and the received/sent totals the preset does expose. Refs: #673
Extend the tracker tests beyond the dry surface: resolve a wallet- and a contract-owned coin to its mt_index, the anchor-block re-read, the not-found failure, and the process-wide singleton. Only the indexer event stream is mocked; the commitment math runs for real, so a resolve proves the tracker computes the commitment the indexer would emit. Refs: #673
The port() guard's promise (an empty, non-numeric, or out-of-range override throws at load time, naming the env var) had no test. Add the three cases. Refs: #673
sort() hid the build order, so the test could not tell serial from concurrent building. Assert the exact order and a max concurrency of one via a counting builder. Also fix the class doc that wrongly said "concurrently"; the builder is serial on purpose (it funds empty signers from the shared deployer). Refs: #673
test:live matches a filename substring, so a name that prefixes others runs them all. Stop advertising a single-file run; say any file matching the name. Refs: #673
Co-authored-by: Andrew Fleming <fleming-andrew@protonmail.com> Signed-off-by: 0xisk <0xisk@proton.me>
Rebasing onto main replays this branch's earlier compile->compact and check->fmt-and-lint rename churn on top of main's #680 rename, which silently reverts the script and Turbo task names back to the old form wherever git saw no conflict. Restore main's compile:*/lint* naming across package.json, turbo.json, the test/bug-report workflows, and scripts/keyIntegrity.ts, and refresh yarn.lock for main's @types/node and fast-check bumps (#685, #686).
a45bda7 to
7f6e09e
Compare
@andrew-fleming I fixed the conflicts with rebase and force push with the main. |
Run the live suite separately from the required PR checks: nightly on `main`, on-demand dispatch, and via the `live-tests` PR label. A plan job reads the live-ready categories from the runner and fans out one job per category, each with its own stack and job budget. Documented in the "Live tests in CI" CONTRIBUTING subsection. Stacked on the live-harness branch (#673); rebases onto main once that merges. Refs: #673
Types of changes
Closes #666
Closes #667
Stands up a live-backend test harness so the existing unit specs can run
against a local Midnight node (
make env-up,MIDNIGHT_BACKEND=live, theunit-livevitest project), and brings the multisig shielded specs green on it.First two sub-issues of the umbrella #665.
What's here
contracts/test-utils/harness/):WalletPool,FundedWallet,LiveSimulatorBackend(deploy-per-create(), per-aliasproviders), plus
funding/dust/network/ledgerEvents/NativeShieldedTokenTrackerand thelive.setup.tscomposition root.fixtures/(address, zswap, shieldedKey,nativeShieldedToken) split from
harness/; vitest configs consolidated intoone
vitest.config.tswithunit/unit-live/integration/harnessprojects.
ShieldedMultiSig→ShieldedProposalMultisig,ShieldedMultiSigV2→ShieldedStatelessMultisig,ShieldedMultiSigV3→NativeShieldedTokenMultisig(CHANGELOG updated).per-alias LevelDB lock contention + coin-PK scoping);
surfaced as a bare "Transaction submission error" on consecutive
same-signer submissions.
testTimeoutto 600s for the ~10-tx lifecycle specs.Scope note
Large diff, but most of it is mechanical: test-utils import-path updates across
suites,
yarn.lock, and the vitest config merge. The substantive new code istest-utils/harness/+test-utils/fixtures/. No production contract behaviorchanges beyond the preset renames.
PR Checklist
Further comments
Opened as a draft: dry suite, tsc, and biome are green, and the heaviest
live subset (
full lifecycle, 3 tests) passes with the sync fix. Flipping toready once the full
ShieldedProposalMultisiglive suite (and the rest of themultisig live specs) are confirmed green on a fresh node. The remaining category
sub-issues (#668–#672) roll out one at a time under #665.
Summary by CodeRabbit
New Features
Updates
Documentation
Bug Fixes