diff --git a/.github/ISSUE_TEMPLATE/01_bug_report.yml b/.github/ISSUE_TEMPLATE/01_bug_report.yml index 82f0a47b6..4056581bf 100644 --- a/.github/ISSUE_TEMPLATE/01_bug_report.yml +++ b/.github/ISSUE_TEMPLATE/01_bug_report.yml @@ -10,7 +10,7 @@ body: value: | Thanks for taking the time to fill out this bug report! - If you’re unsure whether the issue you’re having is a bug, you can post in [Discussions](https://github.com/OpenZeppelin/midnight-contracts/discussions) instead. + If you’re unsure whether the issue you’re having is a bug, you can post in [Discussions](https://github.com/OpenZeppelin/compact-contracts/discussions) instead. - type: checkboxes id: prerequisites @@ -18,11 +18,11 @@ body: label: Prerequisites description: Please ensure you have completed all of the following. options: - - label: I have read the [Contributing Guidelines](https://github.com/OpenZeppelin/midnight-contracts/CONTRIBUTING.md#creating-an-issue). + - label: I have read the [Contributing Guidelines](https://github.com/OpenZeppelin/compact-contracts/blob/main/CONTRIBUTING.md#opening-an-issue). required: true - - label: I agree to follow the [Code of Conduct](https://github.com/OpenZeppelin/midnight-contracts/CODE_OF_CONDUCT.md). + - label: I agree to follow the [Code of Conduct](https://github.com/OpenZeppelin/compact-contracts/blob/main/CODE_OF_CONDUCT.md). required: true - - label: I have searched for [existing issues](https://github.com/OpenZeppelin/midnight-contracts/issues) that already report this problem, without success. + - label: I have searched for [existing issues](https://github.com/OpenZeppelin/compact-contracts/issues) that already report this problem, without success. required: true - type: textarea diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml index b1bfe71ab..a4d7d6bb3 100644 --- a/.github/ISSUE_TEMPLATE/config.yml +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -1,5 +1,5 @@ blank_issues_enabled: false contact_links: - name: OpenZeppelin Midnight Contracts Community Support - url: https://github.com/OpenZeppelin/midnight-contracts/discussions + url: https://github.com/OpenZeppelin/compact-contracts/discussions about: Please ask and answer questions here. diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 1f081dcd7..07a127db3 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -24,7 +24,7 @@ Fixes #??? -- [ ] I have read the [Contributing Guide](../CONTRIBUTING.md#your-first-code-contribution) +- [ ] I have read the [Contributing Guide](../CONTRIBUTING.md#a-typical-workflow) - [ ] I have added tests that prove my fix is effective or that my feature works. See [GUIDELINES.md#testing](../GUIDELINES.md#testing) for more information. - [ ] I have added documentation for new methods or changes to existing method behavior. See [GUIDELINES.md#documentation](../GUIDELINES.md#documentation) for more information. - [ ] CI Workflows Are Passing diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 10b45e4ec..6dd890e6f 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,397 +1,176 @@ # Contributing to OpenZeppelin Contracts for Compact -👍🎉 First off, thanks for taking the time to contribute! 🎉👍 +We really appreciate and value contributions to OpenZeppelin Contracts for Compact. +Please take 5' to review the items listed below to make sure that your contributions are merged as soon as possible. -We really appreciate and value contributions to OpenZeppelin Contracts for Compact. Please take 5' to review the items listed below to make sure that your contributions are merged and questions are answered. +For ANY of the items below, if they seem too complicated or hard, +you can always ask for help from us. +We love that you are helping us, and we would love to help you back! -## Table Of Contents - -[Code of Conduct](#code-of-conduct) - -[I don't want to read this whole thing, I just have a question!!!](#i-dont-want-to-read-this-whole-thing-i-just-have-a-question) - -[What should I know before I get started?](#what-should-i-know-before-i-get-started) - -* [What Is OpenZeppelin Contracts for Compact](#what-is-openzeppelin-contracts-for-compact) -* [Compact Contracts Design Decisions](#compact-contracts-design-decisions) - -[How Can I Contribute?](#how-can-i-contribute) - -* [Reporting Bugs](#reporting-bugs) -* [Suggesting Enhancements](#suggesting-enhancements) -* [Your First Code Contribution](#your-first-code-contribution) -* [Pull Requests](#pull-requests) -* [Opening an Issue](#opening-an-issue) - -[Running Tests](#running-tests) - -* [Unit Tests](#unit-tests) -* [Integration Tests](#integration-tests) -* [Live Tests](#live-tests) - -[Styleguides](#styleguides) - -* [Git Commit Messages](#git-commit-messages) -* [TypeScript Styleguide](#typescript-styleguide) - -[Additional Notes](#additional-notes) - -* [Issue and Pull Request Labels](#issue-and-pull-request-labels) - -## Code of Conduct - -This project and everyone participating in it is governed by the [OpenZeppelin Compact Contracts Code of Conduct](CODE_OF_CONDUCT.md). -By participating, you are expected to uphold this code. -Please report unacceptable behavior to [contact@openzeppelin.com](contact@openzeppelin.com). - -## I don't want to read this whole thing I just have a question!!! - -> **Note:** Please don't file an issue to ask a question. You'll get faster results by using the resources below. - -We have an official message board where the community chimes in with helpful advice if you have questions. - -* [Github Discussions](https://github.com/OpenZeppelin/compact-contracts/discussions) - -## What should I know before I get started? - -### What Is OpenZeppelin Contracts for Compact? - -**A library for secure smart contract development** written in Compact for [Midnight](https://midnight.network/). - -> ## ⚠️ WARNING! ⚠️ -> -> This repo contains highly experimental code. -> Expect rapid iteration. -> **Use at your own risk.** - -### Compact Contracts Design Decisions - -We try our best to document important design decisions, limitations, and pitfalls in each module using the [NatSpec format](https://docs.soliditylang.org/en/latest/natspec-format.html). If you have a question about module that's not answered by this documentation please use the [Discussion Board](https://github.com/OpenZeppelin/compact-contracts/discussions). - -## How Can I Contribute? - -### Reporting Bugs - -This section guides you through submitting a bug report for Compact Contracts. Following these guidelines helps maintainers and the community understand your report :pencil:, reproduce the behavior :computer: :computer:, and find related reports :mag_right:. - -Before creating bug reports, please check [this list](#before-submitting-a-bug-report) as you might find out that you don't need to create one. When you are creating a bug report, please [include as many details as possible](#how-do-i-submit-a-good-bug-report). Fill out [the required template](https://github.com/OpenZeppelin/compact-contracts/blob/main/.github/ISSUE_TEMPLATE/01_BUG_REPORT.yml), the information it asks for helps us resolve issues faster. - -> **Note:** If you find a **Closed** issue that seems like it is the same thing that you're experiencing, open a new issue and include a link to the original issue in the body of your new one. - -#### Before Submitting A Bug Report - -* **Check the [discussions](https://github.com/OpenZeppelin/compact-contracts/discussions)** for a list of common questions and problems. -* **Perform a [cursory search](https://github.com/search?q=repo%3AOpenZeppelin%2Fcompact-contracts%20is%3Aissue&type=issues)** to see if the problem has already been reported. If it has **and the issue is still open**, add a comment to the existing issue instead of opening a new one. - -#### How Do I Submit A (Good) Bug Report? - -Bugs are tracked as [GitHub issues](https://guides.github.com/features/issues/). Create an issue and provide the following information by filling in [the template](https://github.com/OpenZeppelin/compact-contracts/issues/new?template=01_BUG_REPORT.yml). - -Explain the problem and include additional details to help maintainers reproduce the problem: - -* **Use a clear and descriptive title** for the issue to identify the problem. -* **Describe the exact steps which reproduce the problem** in as many details as possible. When listing steps, **don't just say what you did, but explain how you did it**. -* **Provide specific examples to demonstrate the steps**. Include links to files or GitHub projects, or copy/pasteable snippets, which you use in those examples. If you're providing snippets in the issue, use [Markdown code blocks](https://help.github.com/articles/markdown-basics/#multiple-lines). -* **Describe the behavior you observed after following the steps** and point out what exactly is the problem with that behavior. -* **Explain which behavior you expected to see instead and why.** -* **Include screenshots and animated GIFs** which show you following the described steps and clearly demonstrate the problem. - -Include details about your configuration and environment: - -* **Which version of compactc are you using?** You can get the exact version by running `compactc --version` in your terminal. - -### Suggesting Enhancements - -This section guides you through submitting an enhancement suggestion for OpenZeppelin, including completely new features and minor improvements to existing functionality. Following these guidelines helps maintainers and the community understand your suggestion :pencil: and find related suggestions :mag_right:. - -Before creating enhancement suggestions, please check [this list](#before-submitting-an-enhancement-suggestion) as you might find out that you don't need to create one. When you are creating an enhancement suggestion, please [include as many details as possible](#how-do-i-submit-a-good-enhancement-suggestion). Fill in [the template](https://github.com/OpenZeppelin/.github/blob/master/.github/ISSUE_TEMPLATE/02_FEATURE_REQUEST.md), including the steps that you imagine you would take if the feature you're requesting existed. - -#### Before Submitting An Enhancement Suggestion - -* **Check if you're using the latest version of contracts** -* **Perform a [cursory search](https://github.com/search?q=+is%3Aissue+user%3AOpenZeppelin)** to see if the enhancement has already been suggested. If it has, add a comment to the existing issue instead of opening a new one. - -#### How Do I Submit A (Good) Enhancement Suggestion? - -Enhancement suggestions are tracked as [GitHub issues](https://guides.github.com/features/issues/). Create an issue and provide the following information: - -* **Use a clear and descriptive title** for the issue to identify the suggestion. -* **Provide a step-by-step description of the suggested enhancement** in as many details as possible. -* **Provide specific examples to demonstrate the steps**. Include copy/pasteable snippets which you use in those examples, as [Markdown code blocks](https://help.github.com/articles/markdown-basics/#multiple-lines). -* **Describe the current behavior** and **explain which behavior you expected to see instead** and why. -* **Include screenshots and animated GIFs** which help you demonstrate the steps or point out the part of the contracts library the suggestion is related to. -* **Explain why this enhancement would be useful** to most OpenZeppelin contracts users -* **Specify which version of Compact you're using.** You can get the exact version by running `compactc --version` in your terminal - -### Your First Code Contribution - -Unsure where to begin contributing to Compact Contracts? You can start by looking through these `beginner` and `help-wanted` issues: - -* [Beginner issues][beginner] - issues which should only require a few lines of code, and a test or two. -* [Help wanted issues][help-wanted] - issues which should be a bit more involved than `beginner` issues. - -Both issue lists are sorted by total number of comments. While not perfect, number of comments is a reasonable proxy for impact a given change will have. - -### Pull Requests - -The process described here has several goals: - -* Maintain Compact Contracts quality. -* Fix problems that are important to users. -* Engage the community in working toward the best possible Compact smart contracts library. -* Enable a sustainable system for Compact Contract's maintainers to review contributions. - -Any non-trivial code contribution must be first discussed with the maintainers in an issue (see [Opening an issue](#opening-an-issue)). Only very minor changes are accepted without prior discussion. - -Please follow these steps to have your contribution considered by the maintainers: - -1. [Open an issue](#opening-an-issue). -2. Fork the repository and create a new branch. -3. Follow all instructions in [the template](.github/PULL_REQUEST_TEMPLATE.md) -4. Follow the [engineering guidelines](./GUIDELINES.md). -5. Follow the [styleguides](#styleguides) -6. If the PR includes non-trivial changes, additions, or deletions (especially in Compact modules and/or witnesses), -add an entry to the [CHANGELOG](./CHANGELOG.md). -7. After you submit your pull request, verify that all [status checks](https://help.github.com/articles/about-status-checks/) are passing.
What if the status checks are failing? -If a status check is failing, and you believe that the failure is unrelated to your change, please leave a comment on the pull request explaining why you believe the failure is unrelated. -A maintainer will re-run the status check for you. If we conclude that the failure was a false positive, then we will open an issue to track that problem with our status check suite.
- -While the prerequisites above must be satisfied prior to having your pull request reviewed, the reviewer(s) may ask you to complete additional design work, tests, or other changes before your pull request can be ultimately accepted. - -## Running Tests - -Run all commands from the repository root. Enable Corepack once (`corepack enable`) so `yarn` resolves to the version pinned in `package.json`. - -### Unit Tests - -Unit tests run against an in-process mock backend (no network, ZK proving skipped): - -```bash -yarn test -``` - -### Integration Tests - -Composed-contract specs (`contracts/test/integration/specs`): several modules assembled into one contract under `test/integration/_mocks`, then deployed and driven as a unit. Same mock backend as the unit tests. - -```bash -yarn test:integration -``` - -### Live Tests - -Live tests run against a local Midnight network (node, indexer, and proof server) defined in [`local-env.yml`](./local-env.yml). They require [Docker](https://docs.docker.com/get-docker/) and a completed `yarn install`. - -One command runs everything — it compiles, resets the stack, runs a quick harness smoke, then each live-ready category sequentially on a freshly reset node: - -```bash -yarn test:live -``` - -Every `src/` with tests runs live: `multisig`, `token`, `access`, and `security` carry backend-aware specs (real coins and on-chain identity threaded through the wallet pool; coin-flow assertions split into dry and live blocks), and `crypto` and `utils` — pure hashing / commitment / encoding primitives — run their computation through a real deploy on the node too. There is no separate live-ready allowlist; the runner discovers categories automatically (CI reads the list via `--list`). A category that must not run live is an explicit opt-out (`EXCLUDED_CATEGORIES` in [`scripts/live/targets.ts`](./scripts/live/targets.ts) — only legacy `archive` today). - -`integration` is a target of its own, not a category, so an unscoped run skips it. Ask for it by name. Only one live target runs per invocation, since both live projects draw wallets from the same genesis-funded pool. - -```bash -yarn test:live integration # or: yarn test:integration:live -yarn test:live --list # the live targets, as the CI matrix reads them -``` - -> **Note:** the `integration` live target is the harness capability plus a boundary check, not functional coverage. As of ledger v8 the composed contract does not deploy: its circuits' IR overruns the per-tx block byte budget, and the spec asserts that rejection rather than skipping. A ledger bump can move the budget, so a red spec there means the deploy now fits and the functional specs are worth porting to live. - -If any files fail, a second round re-runs just those files on a fresh node with one worker, to separate a real failure from an environment flake: - -* Fails round 1, passes round 2 → **FLAKY** (exit 0, reported loudly). -* Fails both rounds → **REAL** (exit non-zero). - -Scope the same mechanism to one target, or a subset within it. The first argument -names the target (a category, or `integration`). Any further argument is a -filename substring vitest matches, which is the fast loop while iterating on one -feature. Being a substring, a name that prefixes others runs all of them: - -```bash -yarn test:live multisig # the whole category -yarn test:live multisig ShieldedTreasury # any file matching "ShieldedTreasury" -yarn test:live integration ConfidentialFungibleToken # one integration spec -``` - -The filter is resolved against the named target's own spec files, matched the way -vitest matches it (a case-insensitive substring of the path), so it never reaches -into another target's specs. In an unscoped run, a target the filter matches -nothing under is skipped; a filter that matches nothing anywhere aborts the run. - -The two-round flake check still applies to a scoped run, so a green result -means the same thing it does for the full suite. - -The runner owns the stack: it starts it (`make env-up`, itself a reset) and stops it on every exit path, Ctrl-C included. No manual `env:up` or `env:down` needed. To inspect a run afterwards, set `MIDNIGHT_LIVE_KEEP_ENV=1` and stop it yourself. Container logs land in `logs/` either way. - -> **Note:** The live tests all run against one shared node, so state left by an earlier run can make a later one fail. Two rules keep them reliable, both enforced by a guard that fails fast, before any wallet build: -> -> 1. **Start from a fresh node.** State left by a previous run makes shielded spends fail with node `Custom error: 103`. The guard aborts if it finds any shielded coin event beyond genesis. The `test:live*` runner resets for you; reset manually with `yarn env:up`. -> 2. **One live run at a time.** A pid-stamped lock (`contracts/logs/.live-run.lock`) makes a second concurrent run abort. - -Environment knobs: - -| Variable | Default | Effect | -| --- | --- | --- | -| `MIDNIGHT_LIVE_WORKERS` | 3 | Parallel spec files under `unit-live` (max 3, one genesis-funded deployer each). | -| `MIDNIGHT_LIVE_ALLOW_DIRTY` | unset | `1` skips the freshness check (run against a dirty node). | -| `MIDNIGHT_LIVE_MAX_COIN_EVENTS` | 0 | Coin events beyond genesis tolerated before "not fresh". | -| `MIDNIGHT_LIVE_MAX_SCAN_BLOCKS` | 3600 | Above this indexer head, the guard asks you to `env:up` rather than scan. | -| `MIDNIGHT_LIVE_KEEP_ENV` | unset | `1` leaves the stack running after the run instead of tearing it down. | - -`integration-live` runs one worker (only the deployer wallet is in play). `unit-live` runs up to 3 workers in parallel, so their output interleaves. It is tagged per worker: a `▶ live worker N/3 ready` banner when a worker's wallets are funded, a `[wN] ❯ ` line as each spec file starts, and a `[wN] ✓ () [done/total]` line per test — showing the worker, the result, and overall progress through the run. Each worker also writes a detailed log to `logs/live-harness-wN.log`. - -> **Tip:** to save the run to a colored, readable log, force color and pipe to `tee`. Piping (stdout is no longer a TTY) makes vitest print one clean line per result instead of an animated spinner, and `FORCE_COLOR=1` keeps the color. Write it to a `.ansi` file: -> -> ```bash -> FORCE_COLOR=1 yarn test:live multisig 2>&1 | tee logs/live-multisig.ansi -> ``` -> -> The file stores ANSI color codes, so render them rather than reading them raw. In VS Code, an ANSI extension such as [`iliazeus.vscode-ansi`](https://marketplace.visualstudio.com/items?itemName=iliazeus.vscode-ansi) renders a `.ansi` file via **"ANSI Text: Open Preview"**. In a terminal, use `less -R logs/live-multisig.ansi`. On Linux, prefix `systemd-inhibit --why="live tests"` for a long run. - -#### Live tests in CI - -The live suite is too slow for the regular PR checks (hours, not minutes), so [`live.yml`](./.github/workflows/live.yml) runs it separately and is never a required check: - -* **Nightly** on `main`, as the regression safety net. A failed nightly opens (or comments on) a `live-nightly` tracking issue, which closes automatically on the next green run. -* **On demand**: run `Live Test Suite` from the Actions tab (or `gh workflow run live.yml`), optionally scoped with the `target` and `filter` inputs. -* **On a PR**: apply a `live-tests:` label (e.g. `live-tests:multisig`), or `live-tests:all` for every target. Re-apply the label for a fresh run after new pushes. The bare `live-tests` label is rejected by the plan job — with one job per spec file it would queue 60+ checks on the PR, so the full fan-out has to be spelled out. - -The run is one pipeline per live target. A plan job asks the runner which live targets exist (the same list `yarn test:live --list` prints) and which spec files each one holds. Each target then gets a `compile-` job that builds its contract slice once with real ZK keys and uploads it, feeding a `live-` matrix with one job per **spec file** that downloads that build and runs its one file on its own runner, stack, and 6-hour job budget. - -A pipeline per target rather than one compile matrix feeding one suite matrix, because `needs` in Actions is job-level: a single pair of matrices makes every spec file wait for the slowest compile of all targets. Measured on run 32810453735, `utils` compiled in 41s and `crypto` in 67s while `token` and `integration` ran for many minutes, so 15 spec jobs would have idled behind them. There is no per-matrix-leg dependency edge to express this with, so the pairs are literal YAML, their steps living in the `live-compile.yml` and `live-suite.yml` reusable workflows. The cost of that literalness is `KNOWN_TARGETS` in `live.yml`, which the plan job checks against what it discovers: a new `src/` category with no job pair fails the plan in seconds rather than silently never running. - -Per spec file rather than per target because a target is one long serial job, while the files are independent: every suite job resets its own stack, so nothing one spec leaves on the node can fail another, and a failure names the file that caused it. The compile layer is what makes that affordable, since 16 token spec jobs must not mean 16 token compiles. Legs are also budgeted at ~27 minutes of estimated duration: the plan job downloads the previous run's timing reports (best-effort) and weighs each test by its measured duration, falling back to ~55s per test when a file has no history — which reproduces the old 30-test cap exactly. A file over the budget is split by its describe blocks into several legs running the same file under a vitest test-name pattern (`scripts/ci/split.ts`), so no single big file sets the run's wall clock, and a per-test cost far above the fleet's (`MultiToken` runs ~3 min/test) splits its file finer than the count alone would. A file whose structure cannot be filtered exactly (dynamic describe names, say) simply stays one leg; the plan log prints each leg's estimated minutes. - -Every job runs the same `yarn test:live` entry point a local run does, so the two-round flake semantics are identical. The two flags CI adds are `--compile-only` (build the slice and stop) and `--prebuilt` (run against a downloaded build, and abort rather than compile if it is incomplete or carries a truncated key). A target whose compile fails skips its own spec jobs and no others. Each job's verdict lands in its GitHub job summary, the JSON verdict reports upload as a `live-reports--` artifact on every run, and the service and worker logs as `live-logs--` on failure. - -A `filter` input narrows the matrix as well as the run: a target the filter matches no file under gets no job, because one live target that runs nothing is an abort in the runner rather than a pass. A filter that matches nothing anywhere fails the plan job in seconds. The plan job matches it exactly as vitest does, so a filter that works locally is never rejected here. - -The workflow itself holds no logic: resolving that matrix and reporting the nightly both live in [`scripts/live-ci.ts`](./scripts/live-ci.ts), so both are unit tested and runnable locally. +## Opening an issue -```bash -yarn test:scripts # dry unit tests for scripts/live and scripts/ci -yarn types:scripts # type-check them (also part of `yarn types`) +Before starting development, +please [create an issue](https://github.com/OpenZeppelin/compact-contracts/issues/new) to open the discussion, +validate that the change is wanted, and coordinate overall implementation details. + +**Security vulnerabilities are the exception.** +Do not describe a potential vulnerability in a public issue or pull request. +Report it privately as described in [`SECURITY.md`](SECURITY.md) and wait for the maintainers before doing anything public. + +## Creating Pull Requests (PRs) + +As a contributor, you are expected to fork this repository, +work on your own fork and then submit pull requests. +The pull requests will be reviewed and eventually merged into the main repo. +See ["Fork-a-Repo"](https://help.github.com/articles/fork-a-repo/) for how this works. + +## Code quality standards + +Coding conventions live in [`GUIDELINES.md`](GUIDELINES.md): +the single source of truth for naming, section ordering, idioms, testing and documentation. +The design rationale and constraints live in `ARCHITECTURE.md` (coming soon!). +Read them before opening a PR. +The items below are the hard gates your contribution must clear: + +- **Test coverage**: minimum 95% per-file coverage on TypeScript sources (witnesses and simulators), + checked with `yarn test:coverage`. + Compact coverage is reported but not gated. +- **Formatting and linting**: all code must pass the formatter and strict linting + with the commands in [the workflow below](#a-typical-workflow). +- **Conventions**: follow [`GUIDELINES.md`](GUIDELINES.md). +- **Documentation**: add inline documentation for every public API, + formatted per [`GUIDELINES.md`](GUIDELINES.md#documentation). + +## Commit and PR conventions + +The single source of truth for how changes land, and humans and agents follow the same rules: + +- **Sign every commit.** + Configure commit signing before your first contribution; + unsigned commits will not be merged. +- Use [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/) for commit messages: + `type(scope): summary`, e.g. `fix(token): reject zero-amount transfers`. + Pull requests are squash-merged and the PR title becomes the commit message, + so the title must follow the same format. +- **Never add a `Co-Authored-By` trailer for an AI assistant.** + Add one only for a human co-author. + You are accountable for everything you submit under your own name, whatever tools helped produce it. +- Keep the summary short and imperative, + and explain the *why* in the body when it is not obvious from the diff. +- Link the issue in the PR description: + `Fixes #123` / `Resolves #123` closes it on merge and belongs only on a PR that resolves it completely; + for partial work a plain `#123` reference is enough. + Closing keywords act only on PRs targeting the default branch. +- When you make a user-facing change, record it in [`CHANGELOG.md`](CHANGELOG.md) under `## Unreleased`, + grouped by change type (`### Added` / `Changed` / `Fixed` / ...), + following [Keep a Changelog](https://keepachangelog.com/), + and reference the PR number. + +## AI-assisted contributions + +AI coding assistants are welcome (see `AGENTS.md`, coming soon! for the agent setup), +but review thoroughly every line you submit. +What does not change is who is answerable for the result: + +- **You are responsible for the quality of everything you submit, whatever tools produced it.** + Read, understand and test the code before opening a PR. + If you cannot explain why a change is correct, it is not ready. +- **Respect reviewers' time.** + Review bandwidth is the scarcest resource in this project, + and an unreviewed generated diff spends it faster than anything else. +- **Do a local review pass before requesting a human one.** + Run the tests, the formatter and the linter, + then follow the `code-quality` review procedure (see `AGENTS.md`, coming soon! for how to use it with your agent). + Act on what these checks report. + +We may close low-effort AI output without further explanation. + +## A typical workflow + +1. Once, after cloning your fork, add the main repository as `upstream`, + then set up the toolchain (Node via `nvm`, Yarn via Corepack, and the Compact compiler) + as described in the [README](README.md#development): + + ```sh + cd compact-contracts + git remote add upstream https://github.com/OpenZeppelin/compact-contracts.git + ``` + + > NOTE: The directory `compact-contracts` represents your fork's local copy. + +2. Start every change from the current `upstream/main`, with a clean working tree. + Fetch it and branch directly from it. + This works regardless of which branch you are on: + + ```sh + git fetch upstream + git checkout -b fix/some-bug-short-description-123 upstream/main + ``` + + The issue number in the branch name (ex: `fix/typos-in-docs-123`) is for readability only; + the PR is linked to the issue through its description (step 5). + +3. Make your changes, add your files and update documentation. + Run the tests, the formatter and the linter locally and make sure they pass. + For external PRs, the checks on GitHub run once a maintainer approves them. + + ```sh + yarn compile + yarn test + yarn test:coverage + yarn lint:fix + yarn lint + ``` + + Integration and live suites, and how the live suite runs in CI, + are described in [`TESTING.md`](TESTING.md). + +4. Commit (signed) and push to your fork. + + ```sh + git add . + git commit -S -m "fix(token): reject zero-amount transfers" + git push origin fix/some-bug-short-description-123 + ``` + +5. Go to [OpenZeppelin/compact-contracts](https://github.com/OpenZeppelin/compact-contracts) in your web browser and issue a new pull request. + Link the issue in the description as set out in *Commit and PR conventions*, + and make sure all PR checks pass before requesting a review. + +6. Maintainers will review your code and possibly ask for changes before it is pulled into the main repository. + We'll check that all tests pass, review the coding style, and check for general code correctness. + If everything is OK, we'll merge your pull request and your code will be part of OpenZeppelin Contracts for Compact. + + *IMPORTANT*: please pay attention to the maintainer's feedback, + since it's a necessary step to keep up with the standards this project attains to. + +## Tests + +What every change must be tested with, and how tests are laid out, lives in [`GUIDELINES.md`](GUIDELINES.md#testing). +The coverage gate above is the only testing rule this file owns. + +`yarn test` and `yarn test:integration` run against a mock backend and are what CI runs on every PR. +The mock accepts some operations the node rejects, +so a change that touches coins, identity or deployment should also pass live against a local Midnight stack (Docker required) +before you request a review: + +```sh +yarn test:live token # one category, on a freshly reset node +yarn test:live token NativeShieldedToken # files matching a name within it ``` -## Styleguides +The live suite takes hours and is never a required check. +It runs nightly on `main`, and on a PR when a maintainer applies a `live-tests:` label. +Targets, filters, the flake check and the CI layout are in [`TESTING.md`](TESTING.md). -### TypeScript Styleguide +## All set -All TypeScript code is linted with [Biomejs](https://biomejs.dev/). - -Quickly fix all formatting and linting errors with the `yarn lint:fix` command. - -## Opening an issue +If you have any questions, +feel free to post them as an [issue](https://github.com/OpenZeppelin/compact-contracts/issues) +or on [GitHub Discussions](https://github.com/OpenZeppelin/compact-contracts/discussions). -You can [open an issue] to suggest a feature or report a minor bug. For serious bugs please do not open an issue, instead refer to our [security policy] for appropriate steps. - -If you believe your issue may be due to user error and not a problem in the library, consider instead posting a question on the [OpenZeppelin Forum]. - -Before opening an issue, be sure to search through the existing open and closed issues, and consider posting a comment in one of those instead. - -When requesting a new feature, include as many details as you can, especially around the use cases that motivate it. Features are prioritized according to the impact they may have on the ecosystem, so we appreciate information showing that the impact could be high. - -[security policy]: https://github.com/OpenZeppelin/compact-contracts/security -[open an issue]: https://github.com/OpenZeppelin/compact-contracts/issues/new/choose - -## Additional Notes - -### Issue and Pull Request Labels - -This section lists the labels we use to help us track and manage issues and pull requests. - -[GitHub search](https://help.github.com/articles/searching-issues/) makes it easy to use labels for finding groups of issues or pull requests you're interested in. -For example, you might be interested in [open issues across `OpenZeppelin` and all OpenZeppelin-owned packages which are labeled as bugs, but still need to be reliably reproduced](https://github.com/search?utf8=%E2%9C%93&q=is%3Aopen+is%3Aissue+user%3AOpenZeppelin+label%3Abug) or perhaps [open pull requests in `OpenZeppelin/compact-contracts` which haven't been reviewed yet](https://github.com/search?utf8=%E2%9C%93&q=is%3Aopen+is%3Apr+repo%3AOpenZeppelin%2Fcompact-contracts+comments%3A0). -To help you find issues and pull requests, each label is listed with search links for finding open items with that label in `OpenZeppelin/compact-contracts` only and also across all OpenZeppelin repositories. -We encourage you to read about [other search filters](https://help.github.com/articles/searching-issues/) which will help you write more focused queries. - -The labels are loosely grouped by their purpose, but it's not required that every issue has a label from every group or that an issue can't have more than one label from the same group. - -Please open an issue on `OpenZeppelin/compact-contracts` if you have suggestions for new labels, and if you notice some labels are missing on some repositories, then please open an issue on that repository. - -#### Type of Issue and Issue State - -| Label name | `OpenZeppelin/compact-contracts` :mag_right: | `OpenZeppelin`‑org :mag_right: | Description | -| --- | --- | --- | --- | -| `enhancement` | [search][search-OpenZeppelin-repo-label-enhancement] | [search][search-OpenZeppelin-org-label-enhancement] | Feature requests. | -| `bug` | [search][search-OpenZeppelin-repo-label-bug] | [search][search-OpenZeppelin-org-label-bug] | Confirmed bugs or reports that are very likely to be bugs. | -| `question` | [search][search-OpenZeppelin-repo-label-question] | [search][search-OpenZeppelin-org-label-question] | Questions more than bug reports or feature requests (e.g. how do I do X). | -| `feedback` | [search][search-OpenZeppelin-repo-label-feedback] | [search][search-OpenZeppelin-org-label-feedback] | General feedback more than bug reports or feature requests. | -| `help-wanted` | [search][search-OpenZeppelin-repo-label-help-wanted] | [search][search-OpenZeppelin-org-label-help-wanted] | The OpenZeppelin core team would appreciate help from the community in resolving these issues. | -| `beginner` | [search][search-OpenZeppelin-repo-label-beginner] | [search][search-OpenZeppelin-org-label-beginner] | Less complex issues which would be good first issues to work on for users who want to contribute to OpenZeppelin. | -| `more-information-needed` | [search][search-OpenZeppelin-repo-label-more-information-needed] | [search][search-OpenZeppelin-org-label-more-information-needed] | More information needs to be collected about these problems or feature requests (e.g. steps to reproduce). | -| `needs-reproduction` | [search][search-OpenZeppelin-repo-label-needs-reproduction] | [search][search-OpenZeppelin-org-label-needs-reproduction] | Likely bugs, but haven't been reliably reproduced. | -| `blocked` | [search][search-OpenZeppelin-repo-label-blocked] | [search][search-OpenZeppelin-org-label-blocked] | Issues blocked on other issues. | -| `duplicate` | [search][search-OpenZeppelin-repo-label-duplicate] | [search][search-OpenZeppelin-org-label-duplicate] | Issues which are duplicates of other issues, i.e. they have been reported before. | -| `wontfix` | [search][search-OpenZeppelin-repo-label-wontfix] | [search][search-OpenZeppelin-org-label-wontfix] | The OpenZeppelin core team has decided not to fix these issues for now, either because they're working as intended or for some other reason. | -| `invalid` | [search][search-OpenZeppelin-repo-label-invalid] | [search][search-OpenZeppelin-org-label-invalid] | Issues which aren't valid (e.g. user errors). | - -#### Topic Categories - -| Label name | `OpenZeppelin/compact-contracts` :mag_right: | `OpenZeppelin`‑org :mag_right: | Description | -| --- | --- | --- | --- | -| `documentation` | [search][search-OpenZeppelin-repo-label-documentation] | [search][search-OpenZeppelin-org-label-documentation] | Improvements or additions to documentation. | -| `performance` | [search][search-OpenZeppelin-repo-label-performance] | [search][search-OpenZeppelin-org-label-performance] | Improvements related to circuit size, gas optimization, or code efficiency. | -| `security` | [search][search-OpenZeppelin-repo-label-security] | [search][search-OpenZeppelin-org-label-security] | Related to security. | -| `deprecation-help` | [search][search-OpenZeppelin-repo-label-deprecation-help] | [search][search-OpenZeppelin-org-label-deprecation-help] | Issues for helping package authors remove usage of deprecated APIs in packages. | - -#### Pull Request Labels - -| Label name | `OpenZeppelin/compact-contracts` :mag_right: | `OpenZeppelin`‑org :mag_right: | Description -| --- | --- | --- | --- | -| `work-in-progress` | [search][search-OpenZeppelin-repo-label-work-in-progress] | [search][search-OpenZeppelin-org-label-work-in-progress] | Pull requests which are still being worked on, more changes will follow. | -| `needs-review` | [search][search-OpenZeppelin-repo-label-needs-review] | [search][search-OpenZeppelin-org-label-needs-review] | Pull requests which need code review, and approval from maintainers or OpenZeppelin core team. | -| `under-review` | [search][search-OpenZeppelin-repo-label-under-review] | [search][search-OpenZeppelin-org-label-under-review] | Pull requests being reviewed by maintainers or OpenZeppelin core team. | -| `requires-changes` | [search][search-OpenZeppelin-repo-label-requires-changes] | [search][search-OpenZeppelin-org-label-requires-changes] | Pull requests which need to be updated based on review comments and then reviewed again. | -| `needs-testing` | [search][search-OpenZeppelin-repo-label-needs-testing] | [search][search-OpenZeppelin-org-label-needs-testing] | Pull requests which need manual testing. | - -[search-OpenZeppelin-repo-label-enhancement]: https://github.com/search?q=is%3Aopen+is%3Aissue+repo%3AOpenZeppelin%2Fcompact-contracts+label%3Aenhancement -[search-OpenZeppelin-org-label-enhancement]: https://github.com/search?q=is%3Aopen+is%3Aissue+user%3AOpenZeppelin+label%3Aenhancement -[search-OpenZeppelin-repo-label-bug]: https://github.com/search?q=is%3Aopen+is%3Aissue+repo%3AOpenZeppelin%2Fcompact-contracts+label%3Abug -[search-OpenZeppelin-org-label-bug]: https://github.com/search?q=is%3Aopen+is%3Aissue+user%3AOpenZeppelin+label%3Abug -[search-OpenZeppelin-repo-label-question]: https://github.com/search?q=is%3Aopen+is%3Aissue+repo%3AOpenZeppelin%2Fcompact-contracts+label%3Aquestion -[search-OpenZeppelin-org-label-question]: https://github.com/search?q=is%3Aopen+is%3Aissue+user%3AOpenZeppelin+label%3Aquestion -[search-OpenZeppelin-repo-label-feedback]: https://github.com/search?q=is%3Aopen+is%3Aissue+repo%3AOpenZeppelin%2Fcompact-contracts+label%3Afeedback -[search-OpenZeppelin-org-label-feedback]: https://github.com/search?q=is%3Aopen+is%3Aissue+user%3AOpenZeppelin+label%3Afeedback -[search-OpenZeppelin-repo-label-help-wanted]: https://github.com/search?q=is%3Aopen+is%3Aissue+repo%3AOpenZeppelin%2Fcompact-contracts+label%3Ahelp-wanted -[search-OpenZeppelin-org-label-help-wanted]: https://github.com/search?q=is%3Aopen+is%3Aissue+user%3AOpenZeppelin+label%3Ahelp-wanted -[search-OpenZeppelin-repo-label-beginner]: https://github.com/search?q=is%3Aopen+is%3Aissue+repo%3AOpenZeppelin%2Fcompact-contracts+label%3Abeginner -[search-OpenZeppelin-org-label-beginner]: https://github.com/search?q=is%3Aopen+is%3Aissue+user%3AOpenZeppelin+label%3Abeginner -[search-OpenZeppelin-repo-label-more-information-needed]: https://github.com/search?q=is%3Aopen+is%3Aissue+repo%3AOpenZeppelin%2Fcompact-contracts+label%3Amore-information-needed -[search-OpenZeppelin-org-label-more-information-needed]: https://github.com/search?q=is%3Aopen+is%3Aissue+user%3AOpenZeppelin+label%3Amore-information-needed -[search-OpenZeppelin-repo-label-needs-reproduction]: https://github.com/search?q=is%3Aopen+is%3Aissue+repo%3AOpenZeppelin%2Fcompact-contracts+label%3Aneeds-reproduction -[search-OpenZeppelin-org-label-needs-reproduction]: https://github.com/search?q=is%3Aopen+is%3Aissue+user%3AOpenZeppelin+label%3Aneeds-reproduction -[search-OpenZeppelin-repo-label-documentation]: https://github.com/search?q=is%3Aopen+is%3Aissue+repo%3AOpenZeppelin%2Fcompact-contracts+label%3Adocumentation -[search-OpenZeppelin-org-label-documentation]: https://github.com/search?q=is%3Aopen+is%3Aissue+user%3AOpenZeppelin+label%3Adocumentation -[search-OpenZeppelin-repo-label-performance]: https://github.com/search?q=is%3Aopen+is%3Aissue+repo%3AOpenZeppelin%2Fcompact-contracts+label%3Aperformance -[search-OpenZeppelin-org-label-performance]: https://github.com/search?q=is%3Aopen+is%3Aissue+user%3AOpenZeppelin+label%3Aperformance -[search-OpenZeppelin-repo-label-security]: https://github.com/search?q=is%3Aopen+is%3Aissue+repo%3AOpenZeppelin%2Fcompact-contracts+label%3Asecurity -[search-OpenZeppelin-org-label-security]: https://github.com/search?q=is%3Aopen+is%3Aissue+user%3AOpenZeppelin+label%3Asecurity - -[search-OpenZeppelin-repo-label-blocked]: https://github.com/search?q=is%3Aopen+is%3Aissue+repo%3AOpenZeppelin%2Fcompact-contracts+label%3Ablocked -[search-OpenZeppelin-org-label-blocked]: https://github.com/search?q=is%3Aopen+is%3Aissue+user%3AOpenZeppelin+label%3Ablocked -[search-OpenZeppelin-repo-label-duplicate]: https://github.com/search?q=is%3Aopen+is%3Aissue+repo%3AOpenZeppelin%2Fcompact-contracts+label%3Aduplicate -[search-OpenZeppelin-org-label-duplicate]: https://github.com/search?q=is%3Aopen+is%3Aissue+user%3AOpenZeppelin+label%3Aduplicate -[search-OpenZeppelin-repo-label-wontfix]: https://github.com/search?q=is%3Aopen+is%3Aissue+repo%3AOpenZeppelin%2Fcompact-contracts+label%3Awontfix -[search-OpenZeppelin-org-label-wontfix]: https://github.com/search?q=is%3Aopen+is%3Aissue+user%3AOpenZeppelin+label%3Awontfix -[search-OpenZeppelin-repo-label-invalid]: https://github.com/search?q=is%3Aopen+is%3Aissue+repo%3AOpenZeppelin%2Fcompact-contracts+label%3Ainvalid -[search-OpenZeppelin-org-label-invalid]: https://github.com/search?q=is%3Aopen+is%3Aissue+user%3AOpenZeppelin+label%3Ainvalid -[search-OpenZeppelin-repo-label-deprecation-help]: https://github.com/search?q=is%3Aopen+is%3Aissue+repo%3AOpenZeppelin%2Fcompact-contracts+label%3Adeprecation-help -[search-OpenZeppelin-org-label-deprecation-help]: https://github.com/search?q=is%3Aopen+is%3Aissue+user%3AOpenZeppelin+label%3Adeprecation-help - -[search-OpenZeppelin-repo-label-work-in-progress]: https://github.com/search?q=is%3Aopen+is%3Apr+repo%3AOpenZeppelin%2Fcompact-contracts+label%3Awork-in-progress -[search-OpenZeppelin-org-label-work-in-progress]: https://github.com/search?q=is%3Aopen+is%3Apr+user%3AOpenZeppelin+label%3Awork-in-progress -[search-OpenZeppelin-repo-label-needs-review]: https://github.com/search?q=is%3Aopen+is%3Apr+repo%3AOpenZeppelin%2Fcompact-contracts+label%3Aneeds-review -[search-OpenZeppelin-org-label-needs-review]: https://github.com/search?q=is%3Aopen+is%3Apr+user%3AOpenZeppelin+label%3Aneeds-review -[search-OpenZeppelin-repo-label-under-review]: https://github.com/search?q=is%3Aopen+is%3Apr+repo%3AOpenZeppelin%2Fcompact-contracts+label%3Aunder-review -[search-OpenZeppelin-org-label-under-review]: https://github.com/search?q=is%3Aopen+is%3Apr+user%3AOpenZeppelin+label%3Aunder-review -[search-OpenZeppelin-repo-label-requires-changes]: https://github.com/search?q=is%3Aopen+is%3Apr+repo%3AOpenZeppelin%2Fcompact-contracts+label%3Arequires-changes -[search-OpenZeppelin-org-label-requires-changes]: https://github.com/search?q=is%3Aopen+is%3Apr+user%3AOpenZeppelin+label%3Arequires-changes -[search-OpenZeppelin-repo-label-needs-testing]: https://github.com/search?q=is%3Aopen+is%3Apr+repo%3AOpenZeppelin%2Fcompact-contracts+label%3Aneeds-testing -[search-OpenZeppelin-org-label-needs-testing]: https://github.com/search?q=is%3Aopen+is%3Apr+user%3AOpenZeppelin+label%3Aneeds-testing - -[beginner]:https://github.com/search?utf8=%E2%9C%93&q=is%3Aopen+is%3Aissue+label%3Abeginner+label%3Ahelp-wanted+user%3AOpenZeppelin+sort%3Acomments-desc -[help-wanted]:https://github.com/search?q=is%3Aopen+is%3Aissue+label%3Ahelp-wanted+user%3AOpenZeppelin+sort%3Acomments-desc+-label%3Abeginner +Finally, if you're looking to collaborate and want to find easy tasks to start, +look at the issues we marked as ["beginner"](https://github.com/OpenZeppelin/compact-contracts/labels/beginner) +or ["help wanted"](https://github.com/OpenZeppelin/compact-contracts/labels/help%20wanted). +Thanks for your time and code! diff --git a/GUIDELINES.md b/GUIDELINES.md index c831ce494..32484d8ff 100644 --- a/GUIDELINES.md +++ b/GUIDELINES.md @@ -60,14 +60,12 @@ Some other examples of automation are: ## Pull requests -Pull requests are squash-merged to keep the `main` branch history clean. The title of the pull request becomes the commit message, so it should be written in a consistent format: +Pull requests are squash-merged to keep the `main` branch history clean. The title of the pull request becomes the commit message, so it must follow [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/): `type(scope): summary`, e.g. `fix(token): reject zero-amount transfers`. -1) Begin with a capital letter. +1) Keep the summary short and imperative: "add feature X" and not "adds feature X" or "added feature X". 2) Do not end with a period. -3) Write in the imperative: "Add feature X" and not "Adds feature X" or "Added feature X". - -This repository does not follow conventional commits, so do not prefix the title with "fix:" or "feat:". +3) Use the scope to name the module or area the change touches. Work in progress pull requests should be submitted as Drafts and should not be prefixed with "WIP:". -Branch names don't matter, and commit messages within a pull request mostly don't matter either, although they can help the review process. +Branch names don't matter. Commits within a pull request must be signed and follow the same Conventional Commits format; see [`CONTRIBUTING.md`](CONTRIBUTING.md#commit-and-pr-conventions). diff --git a/README.md b/README.md index f0ffbce9c..ac22ed3e6 100644 --- a/README.md +++ b/README.md @@ -233,6 +233,8 @@ yarn compile yarn test ``` +Integration and live suites are described in [TESTING.md](TESTING.md). + ### Check/apply Biome formatter ```bash diff --git a/SUPPORT.md b/SUPPORT.md index f727b2bed..dd100a293 100644 --- a/SUPPORT.md +++ b/SUPPORT.md @@ -3,7 +3,7 @@ If you're looking for support for this library, check out: * Developer Documentation — [Compact Contracts API Documentation](https://docs.openzeppelin.com/contracts-compact/) -* Github Discussion Board — [Github Discussions](https://github.com/OpenZeppelin/midnight-contracts/discussions) +* Github Discussion Board — [Github Discussions](https://github.com/OpenZeppelin/compact-contracts/discussions) * Midnight Forum — [Midnight Forum Technical Questions](https://forum.midnight.network/t/about-the-technical-questions-category/11) On the Midnight Forum, there are a bunch of helpful community members that should be willing to point you in the right direction. \ No newline at end of file diff --git a/TESTING.md b/TESTING.md new file mode 100644 index 000000000..f89d8a4ad --- /dev/null +++ b/TESTING.md @@ -0,0 +1,153 @@ +# Testing + +How to run the test suites locally and how the live suite runs in CI. What every change must +be tested with lives in [`GUIDELINES.md`](GUIDELINES.md#testing); the coverage gate lives in +[`CONTRIBUTING.md`](CONTRIBUTING.md#code-quality-standards). + +Run all commands from the repository root. Enable Corepack once (`corepack enable`) so `yarn` +resolves to the version pinned in `package.json`. + +## Unit tests + +Unit tests run against an in-process mock backend: no network, ZK proving skipped. + +```bash +yarn test +yarn test:coverage # run locally (not yet a CI check) +``` + +## Integration tests + +Composed-contract specs under `contracts/test/integration/specs`: several modules assembled +into one contract under `test/integration/_mocks`, then deployed and driven as a unit. Same +mock backend as the unit tests. + +```bash +yarn test:integration +``` + +## Live tests + +Live tests run against a local Midnight network (node, indexer and proof server) defined in +[`local-env.yml`](local-env.yml). They need [Docker](https://docs.docker.com/get-docker/) and a +completed `yarn install`. The runner builds the target's contracts with real ZK keys, which is +slow; do not interleave `SKIP_ZK=true` builds with live runs, since a key-less build forces a +full regeneration. + +```bash +yarn test:live # every live category, sequentially +yarn test:live multisig # one category +yarn test:live multisig ShieldedTreasury # files within a category +yarn test:live integration # the composed-contract specs (or: yarn test:integration:live) +yarn test:live --list # the live targets, as the CI matrix reads them +``` + +A run compiles the target's slice, starts the stack (`make env-up`, itself a reset), runs a +harness smoke, then the specs, each category on a freshly reset node. The runner stops the +stack on every exit path, Ctrl-C included; no manual `env:up` or `env:down` is needed. +`MIDNIGHT_LIVE_KEEP_ENV=1` leaves it running for inspection. Container logs land in `logs/` +either way. + +### Targets and filters + +Every `contracts/src/` with tests is a live category; today that is `access`, +`crypto`, `multisig`, `security`, `token` and `utils`. A category that must not run live is +an explicit opt-out in `EXCLUDED_CATEGORIES` in [`scripts/live/targets.ts`](scripts/live/targets.ts) +(only the legacy `archive` today). + +`integration` is a target of its own, not a category: an unscoped run skips it, so ask for it +by name. Only one target runs per invocation, since both live projects draw wallets from the +same genesis-funded pool. The integration live block deploys the composed contract and reads +its supply back; the functional integration specs stay dry-only because they mutate private +state mid-test, which the live backend rejects. + +The first argument names the target. Any further argument is a filename filter, matched the +way vitest matches it (a case-insensitive substring of the path) against that target's own +spec files, so a name that prefixes others runs all of them. In an unscoped run, a target the +filter matches nothing under is skipped; a filter that matches nothing anywhere aborts. + +### Flake check and exit codes + +If any files fail, a second round re-runs just those files on a fresh node with one worker: + +- Fails round 1, passes round 2: **FLAKY** (exit 0, reported loudly). +- Fails both rounds, or never reports in round 2: **REAL** (exit 1). +- Infrastructure abort (stack, compile, lock): exit 2. + +The same semantics apply to a scoped run, so a green result means the same thing as for the +full suite. + +### Fresh node rules + +All live tests share one node, so state left by an earlier run can fail a later one. A guard +enforces two rules and fails fast, before any wallet build: + +1. **Start from a fresh node.** Stale state makes shielded spends fail with node + `Custom error: 103`. The guard aborts if it finds any shielded coin event beyond genesis. + The runner resets for you; reset manually with `yarn env:up`. +2. **One live run at a time.** A pid-stamped lock (`contracts/logs/.live-run.lock`) makes a + second concurrent run abort. + +| Variable | Default | Effect | +| --- | --- | --- | +| `MIDNIGHT_LIVE_WORKERS` | 3 | Parallel spec files under `unit-live` (max 3, one genesis-funded deployer each). | +| `MIDNIGHT_LIVE_ALLOW_DIRTY` | unset | `1` skips the freshness check. | +| `MIDNIGHT_LIVE_MAX_COIN_EVENTS` | 0 | Coin events beyond genesis tolerated before "not fresh". | +| `MIDNIGHT_LIVE_MAX_SCAN_BLOCKS` | 3600 | Above this indexer head, the guard asks you to `env:up` rather than scan. | +| `MIDNIGHT_LIVE_KEEP_ENV` | unset | `1` leaves the stack running after the run. | + +### Reading the output + +`unit-live` runs up to 3 workers in parallel, so output interleaves. It is tagged per worker: +a `▶ live worker N/3 ready` banner when a worker's wallets are funded, a `[wN] ❯ ` line +as each spec file starts, and a `[wN] ✓ () [done/total]` line per test. Each worker +also writes `logs/live-harness-wN.log`. `integration-live` runs one worker. + +To keep a readable log, force color and pipe to `tee`: piping makes vitest print one line per +result instead of a spinner, and `FORCE_COLOR=1` keeps the color. + +```bash +FORCE_COLOR=1 yarn test:live multisig 2>&1 | tee logs/live-multisig.ansi +``` + +Render the `.ansi` file rather than reading it raw: `less -R` in a terminal, or an ANSI +extension such as [`iliazeus.vscode-ansi`](https://marketplace.visualstudio.com/items?itemName=iliazeus.vscode-ansi) +in VS Code. On Linux, prefix `systemd-inhibit --why="live tests"` for a long run. + +### Live tests in CI + +The live suite takes hours, so [`live.yml`](.github/workflows/live.yml) runs it separately +from the PR checks and is never a required check: + +- **Nightly** on `main`. A failed nightly opens (or comments on) a `live-nightly` tracking + issue, which closes automatically on the next green run. +- **On demand**: run `Live Test Suite` from the Actions tab (or `gh workflow run live.yml`), + optionally scoped with the `target` and `filter` inputs. +- **On a PR**: apply a `live-tests:` label (e.g. `live-tests:multisig`), or + `live-tests:all` for every target. Re-apply the label for a fresh run after new pushes. The + bare `live-tests` label is rejected by the plan job. + +The run is one pipeline per target. A plan job asks the runner which targets exist and which +spec files each holds. Each target gets a compile job that builds its slice once with real ZK +keys, feeding a matrix with one job per spec file that runs its file on its own runner and +stack. A file whose estimated duration exceeds the leg budget (30 tests at ~55 s each, or the +previous run's measured timings when available) is split by its describe blocks into several +legs via [`scripts/ci/split.ts`](scripts/ci/split.ts). `KNOWN_TARGETS` in `live.yml` must +list every target; a new `src/` category without a job pair fails the plan in seconds. The +reasoning behind this layout is in the header comment of `live.yml`. + +Every job runs the same `yarn test:live` entry point a local run does, so the flake semantics +are identical. The two flags CI adds are `--compile-only` (build the slice and stop) and +`--prebuilt` (run against a downloaded build, and abort rather than compile if it is +incomplete). A `filter` input narrows the matrix as well as the run, matched exactly as vitest +does. Each job's verdict lands in its job summary; JSON reports upload as a +`live-reports--` artifact on every run, and service and worker logs as +`live-logs--` on failure. + +The workflow holds no logic: matrix resolution and nightly reporting live in +[`scripts/live-ci.ts`](scripts/live-ci.ts), so both are unit tested and runnable locally. + +```bash +yarn test:scripts # dry unit tests for scripts/live and scripts/ci +yarn types:scripts # type-check them (also part of `yarn types`) +``` diff --git a/scripts/live/targets.ts b/scripts/live/targets.ts index f80c1c3ff..3f3a9f71d 100644 --- a/scripts/live/targets.ts +++ b/scripts/live/targets.ts @@ -88,7 +88,7 @@ export function resolvePlan( const scoped = !integration && args.length > 0 && allCategories.includes(args[0]); - // The first positional arg always names the target (CONTRIBUTING.md). If it is + // The first positional arg always names the target (TESTING.md). If it is // present but names neither an active live category — an excluded one like // `archive`, or a typo — nor `integration`, reject it here so the caller can // fail fast, BEFORE the expensive compile / env-up / harness-smoke setup (no