Skip to main content

run-guardian-qualification

Set up and run the end-to-end qualification suite in this repository: the deterministic profile against a provisioned stack, and the live profile driving real Miden transactions from a CI-held treasury. Use when Codex needs to run or debug `qualification/stack/run.sh`, add or change a scenario, drive one SDK's live scenarios against testnet, reproduce a qualification failure locally, or interpret a run result's outcome classes and qualification claim.

来源信息

仓库
OpenZeppelin/guardian
最近来源活动
2026年9月24日 11:49
检测到的 SKILL.md 语言
英语
星标
10
分支
20

安装方式

默认使用会先检查来源的 Prompt;你也可以切换为直接命令,或下载本地副本。

检查来源文件

决定是否安装前,请先阅读 SKILL.md,以及 SkillsMP 当前展示的配套文件。

文件资源管理器
2 个文件

正在显示 SKILL.md

SKILL.md
来源说明 · 只读预览
name
run-guardian-qualification
description
Set up and run the end-to-end qualification suite in this repository: the deterministic profile against a provisioned stack, and the live profile driving real Miden transactions from a CI-held treasury. Use when Codex needs to run or debug `qualification/stack/run.sh`, add or change a scenario, drive one SDK's live scenarios against testnet, reproduce a qualification failure locally, or interpret a run result's outcome classes and qualification claim.
# Run Guardian Qualification Two profiles. **Deterministic** provisions a stack and drives fixture flows with no chain; it is fast enough to gate merges. **Live** drives real transactions on a public Miden network and spends real funds. Read [`docs/QUALIFICATION.md`](../../../docs/QUALIFICATION.md) for what the suite covers and what it deliberately does not. This skill is how to run it. ## Pick the smallest thing that answers the question | Question | Command | |---|---| | Does the manifest hold together? | `./target/debug/qualification-driver validate` | | Does driver logic still work? | `cargo test -p guardian-qualification-driver` | | Do the shell libs still work? | `qualification/stack/tests/harness-test.sh` | | Does a scenario body work? | one scenario, one SDK, against a hand-started server | | Does the assembled system work? | `qualification/stack/run.sh` with Docker | Do not reach for the full stack to debug a scenario body. It rebuilds an image. ## Build the binary first, always ```bash cargo build -p guardian-qualification-driver ``` `qualification/stack/run.sh` invokes the driver through `cargo run`, which builds it if needed. The TypeScript leg's funding bridge does not: it shells out to `target/debug/qualification-driver` (override with `QUAL_DRIVER_BIN`), because `cargo run` costs about 3.5s of build-graph checking per call and can stall on a rebuild in the middle of a chain operation. The commands below use the built binary directly for the same reason. ## Fast path: one scenario, no Docker The quickest loop for scenario work. Start a server with `cargo` directly, then drive one scenario. Deterministic scenarios need the **fixture** acknowledgement key: the committed fixture account binds one specific guardian identity, and a server booted with a generated key rejects it with `403 ... not an authorized signer`. Point `GUARDIAN_ACK_FALCON_SECRET_PATH` at a file containing `guardian_secret_key` from `crates/server/src/testing/fixtures/keys.json`, or accept that only the live and error-envelope scenarios will pass. ```bash # Rust, one live scenario export QUAL_TREASURY_KEY="$QUAL_TREASURY_KEY_testnet" # from qualification/.treasury-secrets.env ./target/debug/qualification-driver run \ --profile live --network testnet --sdk rust \ --scenario live-execute-2of3-falcon \ --run-id local-$(date +%s) \ --http-endpoint http://127.0.0.1:3000 \ --grpc-endpoint http://127.0.0.1:50051 \ --out /tmp/qual-results/result.json ``` ```bash # TypeScript, same scenario cd packages/miden-multisig-client QUAL_PROFILE=live QUAL_NETWORK=testnet \ QUAL_SCENARIOS=live-execute-2of3-falcon \ QUAL_HTTP_ENDPOINT=http://127.0.0.1:3000 \ QUAL_GRPC_ENDPOINT=http://127.0.0.1:50051 \ QUAL_OUT_DIR=/tmp/qual-results QUAL_RUN_ID=local-$(date +%s) \ npx vitest run --config vitest.qualification.config.ts ``` The two drivers reach GUARDIAN over **different transports**: Rust speaks gRPC, TypeScript speaks HTTP. Passing one the other's endpoint fails in ways that look like an outage. ## Full stack ```bash qualification/stack/run.sh --profile deterministic qualification/stack/run.sh --profile live --network testnet ``` `--keep-stack` leaves the containers up so you can read logs; without it the stack is torn down even on failure, and diagnostics land in `<out>/diagnostics/`. **Any change under `crates/` rebuilds the server image.** The build context copies the workspace, so a one-line driver edit costs a full release build before the stack starts. This is the main reason to iterate against a hand-started server and use the stack only to confirm. **Never edit `run.sh` while a run is in flight.** Bash reads scripts incrementally, so an edit mid-run produces a syntax error at a stale byte offset in a file that passes `bash -n`. Wait for the run, then edit. The stack starts a **second GUARDIAN** (`server-migration-target`) with its own acknowledgement identity and its own database, because migrating an account to the GUARDIAN it already uses is not a state change and the kernel rejects it. It exports `QUAL_GUARDIAN_MIGRATION_GRPC` and `QUAL_GUARDIAN_MIGRATION_HTTP`; the migration scenario reports environment-blocked when they are absent. ## Treasury Live runs need `QUAL_TREASURY_KEY`. Locally it lives in `qualification/.treasury-secrets.env` (gitignored, mode 0600) with one key per network. ```bash set -a && . qualification/.treasury-secrets.env && set +a export QUAL_TREASURY_KEY="$QUAL_TREASURY_KEY_testnet" ./target/debug/qualification-driver treasury-status --network testnet ``` `treasury-address` prints the address to fund from the faucet; `treasury-bootstrap` consumes the faucet notes into the vault. The treasury is a **public** single-signature wallet on purpose: a private one keeps its state only in the local store, which a fresh CI runner does not have, so the next transaction would build on a stale nonce. Do not arm the GitHub secret until the `qualification-{devnet,testnet}` environments have their deployment branches locked to the default branch. ## Changing scenarios Scenario sources are data, not code: `qualification/manifest/scenarios.toml` and `matrix.toml`. After editing either: ```bash ./target/debug/qualification-driver export-manifest --out qualification/manifest/manifest.json ./target/debug/qualification-driver validate ``` A committed `manifest.json` that does not match the sources fails a test. The validator also refuses a scenario whose step budget exceeds a network's historical window while required there, so exclude it for that network rather than shrinking a budget the flow cannot meet. A new action needs **six edits across five files**, and missing any one fails closed on a required scenario rather than silently skipping: the `Action` variant and its `From<String>` arm in `manifest/mod.rs`, the Rust dispatch in `scenario/mod.rs`, the Rust body in `scenario/{live,account,identity,error_envelope}.rs`, the TypeScript dispatch in `runner.ts`, and the TypeScript body in `actions/{live,account,identity,errorEnvelope,operator}.ts`. The body goes in the file for the action's family, not always `live`. A scenario that only composes existing actions needs no driver code at all. The full procedure, including the matrix and the negative control, is in `docs/QUALIFICATION.md`, "Adding a scenario". ## Reading a result `conclusion` is the gate. `qualification_claim` is the coverage statement, and the two are independent: a run can conclude successfully and still claim only `partial`, because a required scenario that skipped or was environment-blocked forfeits the claim without failing the run. | Outcome | Meaning | |---|---| | `passed` | the flow completed and was verified | | `failed` + `product` | the system under test is wrong | | `failed` + `setup` | the harness or environment is wrong | | `skipped` | a known capability gap, named in the reason | | `environment_blocked` | the network or a dependency stopped it | Exit codes: 0 concluded, 1 product failure, 2 setup failure, 3 environment blocked and nothing else ran. **A zero exit is not full coverage**, so read the claim. The TypeScript leg writes `<run-id>-typescript.json` carrying only `run_id` and `scenario_results`; the Rust merger folds it into the run and restates the claim over both SDKs. Merge with `qualification-driver report --results <dir>`. ## Negative controls A suite that has never failed is not known to detect anything. Before trusting a green run after changing assertion logic, break the thing deliberately and confirm a **named** scenario fails. The procedure and the two recorded controls are in [`qualification/README.md`](../../../qualification/README.md). Do not ship a fault-injection switch to make this easier. A switch that disables an assertion is a switch that can be left on. ## Gotchas that cost real time - **TypeScript needs an HTTP/2 shim** to reach Miden at all from Node, and without a reachable remote prover the SDK silently falls back to in-WASM proving at roughly twenty-five times the CPU. `tests/qualification/h2Fetch.ts` is the workaround. - **The qualification tests typecheck under their own config.** `tsconfig.json` covers only `src/`. Run `npm run typecheck:tests` in `packages/miden-multisig-client`, or a missing import ships. - **A stalled image build is usually the network, not the Dockerfile.** A cargo fetch through a VM NAT can stall with zero bytes transferred. Re-run it before changing anything; `CARGO_HTTP_MULTIPLEXING=false` in the build environment trades roughly a third more fetch time for one connection per download, and is worth reaching for only if the stall reproduces. - **GUARDIAN holds one acknowledgement identity per signature scheme.** Asking for the pubkey without a scheme returns the default, and an ECDSA account built from it is refused at registration with a message about authorization rather than the mismatch. - **A proposal leaving the pending set is not completion.** A discarded delta is removed the same way. Assert through `verify_state_commitment` / `verifyStateCommitment` plus canonical delta history, which is what the drivers now do. ## Before calling a change done ```bash cargo test -p guardian-qualification-driver cargo clippy -p guardian-qualification-driver --all-targets cargo fmt --all -- --check qualification/stack/tests/harness-test.sh cd packages/miden-multisig-client && npm run typecheck:tests && npx vitest run ``` Live scenario changes are not verified by any of the above. Run the affected scenario on testnet for **both** SDKs, since the two drivers diverge in ways the type system does not catch.
在 GitHub 查看