Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
54 commits
Select commit Hold shift + click to select a range
06410b6
Reject unusable Ed25519 identity public keys
mellowcroc Aug 13, 2026
096bfd8
Accept more than two audits in a production decision
mellowcroc Aug 14, 2026
2e90bea
Report chain replay progress on stderr
mellowcroc Aug 13, 2026
bc0ab28
Add audit change list and a local ceremony runbook
mellowcroc Aug 13, 2026
a37c27f
Reject untrimmed whitespace in attested string fields
mellowcroc Aug 13, 2026
ea03eee
Keep on-curve validation when skipping subgroup checks
mellowcroc Aug 13, 2026
e9743f5
Bound untrusted decode paths against allocation DoS
mellowcroc Aug 13, 2026
44cf9f9
Clone before handing retained states to gnark
mellowcroc Aug 14, 2026
150abd8
Reject characters that make a name render as other than its bytes
mellowcroc Aug 15, 2026
07dd99a
Track the ceremony attack/defense inventory
mellowcroc Aug 15, 2026
bb39e3d
Derive the beacon round from the clock sampled after replay
mellowcroc Aug 16, 2026
6e2529e
Report replay progress from the phase 1 seal
mellowcroc Aug 16, 2026
d85ee0d
Report stage progress from phase 2 initialization
mellowcroc Aug 16, 2026
b921a60
Derive the public evidence vector at the pinned golden path
mellowcroc Aug 17, 2026
c4d4dc5
Redact diagnostics by construction, matching short values per token
mellowcroc Aug 18, 2026
612ce74
Add a read-only inspect command for recovery state
mellowcroc Aug 18, 2026
1f82c96
Track the change list in the pull request instead of the tree
mellowcroc Aug 18, 2026
b7b9aa6
Reserve a witness observation window in production closes
mellowcroc Aug 18, 2026
5a5a21d
Align counted gates across layers so diligence cannot strand a release
mellowcroc Aug 18, 2026
9c0f6dc
Rename the audits gate before any record freezes the old name
mellowcroc Aug 18, 2026
61a4a1e
Add brokerless MPC ceremony inspection and receipts
mellowcroc Aug 18, 2026
7a652a6
Refresh and compress the attack/defense inventory
mellowcroc Aug 18, 2026
8076f9e
Merge pull request #1 from zksecurity/audit/ed25519-key-validation
mellowcroc Aug 19, 2026
c57b898
Merge pull request #4 from zksecurity/feature/mpc-relay-ops
mellowcroc Aug 19, 2026
411adc2
fix untrusted decode preflight bypasses
mellowcroc Aug 19, 2026
5c4d422
Merge pull request #2 from zksecurity/harden/untrusted-decode-dos
mellowcroc Aug 19, 2026
1aca232
add MPC ceremony release gates
mellowcroc Aug 19, 2026
528f556
remove ineffectual replay assignments
mellowcroc Aug 19, 2026
5f6dce2
Merge pull request #6 from zksecurity/agent/mpc-release-gates
mellowcroc Aug 19, 2026
14c449a
Wait for the auto-install before driving the developer controls
mellowcroc Aug 20, 2026
4b9205d
Merge pull request #7 from zksecurity/fix/desktop-install-test-race
mellowcroc Aug 20, 2026
c1fd3e6
add downloadable tiny ceremony initializer
mellowcroc Aug 20, 2026
2643d62
perf(mpc): parallelize ceremony hot paths
mellowcroc Aug 20, 2026
14600b0
fix(mpc): harden rehearsal finalization recovery
mellowcroc Aug 20, 2026
44aa96c
ci(mpc): verify patched Relay integration
mellowcroc Aug 20, 2026
065cb79
docs: remove local MPC ceremony runbook
mellowcroc Aug 20, 2026
bf8cc7b
docs: remove MPC ceremony reference documents
mellowcroc Aug 20, 2026
76e442d
test: allow full proof gate to complete
mellowcroc Aug 20, 2026
93d20cd
docs(mpc-ceremony): finalize help reflects circuit-from-definition (#9)
mellowcroc Aug 20, 2026
4fb8adf
ci(mpc): allow full Relay compatibility runtime
mellowcroc Aug 20, 2026
1f0bc72
Merge remote-tracking branch 'origin/main' into feature/downloadable-…
mellowcroc Aug 20, 2026
d08166c
Merge pull request #10 from zksecurity/feature/downloadable-rehearsal…
mellowcroc Aug 20, 2026
37f774a
Merge remote-tracking branch 'origin/main' into perf/mpc-ceremony-par…
mellowcroc Aug 20, 2026
d51c2a3
Merge pull request #8 from zksecurity/perf/mpc-ceremony-parallel-hot-…
mellowcroc Aug 20, 2026
7856824
ci: decouple mpc release validation from Relay
mellowcroc Aug 20, 2026
197e159
docs: replace stale MPC runbook links
mellowcroc Aug 20, 2026
16a609c
docs: describe full binary compatibility gate
mellowcroc Aug 20, 2026
f233434
Merge pull request #12 from zksecurity/decouple-relay-compatibility
mellowcroc Aug 20, 2026
619660c
fix(mpc): pin the canonical production circuit at init
mellowcroc Aug 20, 2026
a508eef
Merge pull request #13 from zksecurity/fix/pin-canonical-production-c…
mellowcroc Aug 20, 2026
a81f800
fix: harden production release validation
mellowcroc Aug 20, 2026
dc1cad1
fix: pin Go 1.26.6 toolchain hashes
mellowcroc Aug 20, 2026
52fbf7f
Merge pull request #14 from zksecurity/fix/release-security-blockers
mellowcroc Aug 20, 2026
04a9fa5
feat: generate ceremony signing identities
mellowcroc Sep 4, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,12 @@ jobs:
- name: Test
run: go test -timeout 15m ./...

- name: Race-sensitive MPC parallel paths
run: |
go test -race -count=1 \
github.com/consensys/gnark/backend/groth16/bls12-381/mpcsetup
go test -race -count=1 ./internal/mpcceremony

- name: WASM prover builds
run: |
GOOS=js GOARCH=wasm go build -o /dev/null ./cmd/wasm-prover
Expand Down
118 changes: 118 additions & 0 deletions .github/workflows/mpc-ceremony-release-validation.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
name: MPC ceremony release validation

on:
push:
branches: [main]
pull_request:
workflow_dispatch:

permissions:
contents: read

concurrency:
group: mpc-ceremony-release-${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: ${{ github.ref != 'refs/heads/main' }}

jobs:
rehearsal-reproducibility:
name: Reproducible unsigned rehearsal
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
fetch-depth: 0
persist-credentials: false

- uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0
with:
go-version-file: go.mod
cache: false

- name: Verify release inputs
shell: bash
run: |
test "$(go env GOVERSION)" = go1.26.6
test "$(go env GOHOSTOS)" = linux
test "$(go env GOHOSTARCH)" = amd64
test "$(sed -n 's/^module //p' go.mod)" = proof-tool

- name: Bootstrap patched vendor tree
run: bash scripts/bootstrap-vendor.sh

- name: Build two unsigned rehearsals
shell: bash
run: |
mkdir "$RUNNER_TEMP/mpc-rehearsal-a-parent"
mkdir "$RUNNER_TEMP/mpc-rehearsal-b-parent"
scripts/build-mpc-ceremony-release.sh \
--mode rehearsal \
--out-dir "$RUNNER_TEMP/mpc-rehearsal-a-parent/release"
scripts/build-mpc-ceremony-release.sh \
--mode rehearsal \
--out-dir "$RUNNER_TEMP/mpc-rehearsal-b-parent/release"

- name: Verify byte-for-byte reproducibility
shell: bash
run: |
scripts/verify-mpc-ceremony-reproducible.sh \
--mode rehearsal \
--expected-commit "$GITHUB_SHA" \
--expected-tag none \
--tag-signer-fingerprint none \
--trusted-build-public-key-file none \
"$RUNNER_TEMP/mpc-rehearsal-a-parent/release" \
"$RUNNER_TEMP/mpc-rehearsal-b-parent/release"

- name: Exercise download-only tiny rehearsal initialization
shell: bash
run: |
set -euo pipefail
ceremony_binary="$RUNNER_TEMP/mpc-rehearsal-a-parent/release/mpc-ceremony"
rehearsal_root="$RUNNER_TEMP/downloadable-tiny-rehearsal"
"$ceremony_binary" rehearsal init \
--created-at 2026-08-20T06:00:00Z \
--out-dir "$rehearsal_root"
"$ceremony_binary" --format json inspect definition \
--ceremony "$rehearsal_root/public/ceremony.json" \
--ceremony-signature "$rehearsal_root/public/ceremony.sig" \
--coordinator-public-key-file \
"$rehearsal_root/public/coordinator-public-key.hex" \
>"$RUNNER_TEMP/downloadable-tiny-definition.json"
python3 - "$RUNNER_TEMP/downloadable-tiny-definition.json" <<'PY'
import json
import sys

with open(sys.argv[1], "rb") as handle:
result = json.load(handle)
inspection = result["definition_inspection"]
assert result["ok"] is True
assert inspection["mode"] == "rehearsal"
assert inspection["phase1_participants"] == [
"participant-01", "participant-02", "participant-03"
]
PY
test -f "$rehearsal_root/config/environment.json"
test -f "$rehearsal_root/keys/coordinator.ed25519.private.hex"
test "$(stat -c %a "$rehearsal_root/keys/coordinator.ed25519.private.hex")" = 600
if "$ceremony_binary" rehearsal init \
--created-at 2026-08-20T06:00:01Z \
--out-dir "$rehearsal_root"; then
echo "rehearsal initializer overwrote an existing root" >&2
exit 1
fi
test -f "$rehearsal_root/public/ceremony.json"

- name: Confirm rehearsal packages are unsigned
shell: bash
run: |
for release in \
"$RUNNER_TEMP/mpc-rehearsal-a-parent/release" \
"$RUNNER_TEMP/mpc-rehearsal-b-parent/release"
do
test "$(<"$release/build-mode.txt")" = rehearsal
test "$(<"$release/signed-tag.txt")" = none
test "$(<"$release/signed-tag-status.txt")" = not-required-for-rehearsal
test ! -e "$release/build-package-manifest.sig"
test ! -e "$release/build-package-manifest-public-key.hex"
done
64 changes: 32 additions & 32 deletions .github/workflows/release-proof-helper.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,18 +12,13 @@ on:
required: true
default: false
type: boolean
signed_release:
description: Mark release notes as signed. Use only after Authenticode signatures are verified.
required: true
default: false
type: boolean

permissions:
contents: write
contents: read

env:
PROOF_HELPER_APP_DIR: apps/proof-helper-desktop
PROOF_HELPER_TAURI_DIR: apps/proof-helper-desktop/src-tauri
PROOF_HELPER_RELEASE_TAG: ${{ inputs.tag }}
WINDOWS_TARGET: x86_64-pc-windows-msvc
WINDOWS_SIDECAR: proof-tool-x86_64-pc-windows-msvc.exe
# Production origin the desktop helper pairs and opens by default.
Expand All @@ -37,25 +32,32 @@ jobs:
name: Release checks
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4
with:
persist-credentials: false

- name: Refuse reserved portable-helper tag
shell: bash
run: |
if [[ "${{ inputs.tag }}" == "proof-helper-v0.1.0" ]]; then
if [[ "$PROOF_HELPER_RELEASE_TAG" == "proof-helper-v0.1.0" ]]; then
echo "::error::proof-helper-v0.1.0 is reserved for portable fixture-helper bundles. Use a new desktop tag."
exit 1
fi
if [[ ! "$PROOF_HELPER_RELEASE_TAG" =~ ^proof-helper-desktop-v[0-9A-Za-z][0-9A-Za-z._-]*$ ]] ||
! git check-ref-format "refs/tags/$PROOF_HELPER_RELEASE_TAG"; then
echo "::error::tag must be a valid proof-helper-desktop-v... Git tag"
exit 1
fi

- uses: actions/setup-go@v5
- uses: actions/setup-go@40f1582b2485089dde7abd97c1529aa768e1baff # v5
with:
go-version-file: go.mod

- uses: pnpm/action-setup@v4
- uses: pnpm/action-setup@f40ffcd9367d9f12939873eb1018b921a783ffaa # v4
with:
version: 10.18.3

- uses: actions/setup-node@v4
- uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4
with:
node-version: 24
cache: pnpm
Expand All @@ -64,7 +66,7 @@ jobs:
apps/ownership-proof-web/pnpm-lock.yaml
apps/proof-helper-desktop/pnpm-lock.yaml

- uses: dtolnay/rust-toolchain@stable
- uses: dtolnay/rust-toolchain@4360b52568e2003a75bf9bc1d59f33a8e3fc893c # stable

- name: Linux Tauri system dependencies
run: |
Expand Down Expand Up @@ -123,23 +125,25 @@ jobs:
needs: checks
runs-on: windows-latest
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4
with:
persist-credentials: false

- uses: actions/setup-go@v5
- uses: actions/setup-go@40f1582b2485089dde7abd97c1529aa768e1baff # v5
with:
go-version-file: go.mod

- uses: pnpm/action-setup@v4
- uses: pnpm/action-setup@f40ffcd9367d9f12939873eb1018b921a783ffaa # v4
with:
version: 10.18.3

- uses: actions/setup-node@v4
- uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4
with:
node-version: 24
cache: pnpm
cache-dependency-path: apps/proof-helper-desktop/pnpm-lock.yaml

- uses: dtolnay/rust-toolchain@stable
- uses: dtolnay/rust-toolchain@4360b52568e2003a75bf9bc1d59f33a8e3fc893c # stable
with:
targets: x86_64-pc-windows-msvc

Expand Down Expand Up @@ -173,11 +177,9 @@ jobs:
- name: Stage Windows release artifacts
working-directory: apps/proof-helper-desktop
shell: bash
env:
PROOF_HELPER_WINDOWS_SIGNED: ${{ inputs.signed_release && '1' || '0' }}
run: |
pnpm release:stage-windows -- \
--tag "${{ inputs.tag }}" \
--tag "$PROOF_HELPER_RELEASE_TAG" \
--bundle-dir "src-tauri/target/x86_64-pc-windows-msvc/release/bundle" \
--sidecar "src-tauri/binaries/proof-tool-x86_64-pc-windows-msvc.exe" \
--out-dir "../../dist/proof-helper-windows-x64"
Expand All @@ -186,22 +188,18 @@ jobs:
shell: bash
run: |
mkdir -p dist/proof-helper-windows-x64
signing_status="Unsigned preview"
if [[ "${{ inputs.signed_release }}" == "true" ]]; then
signing_status="Signed release"
fi
{
echo "Proof Helper Windows ${{ inputs.tag }}"
echo "Proof Helper Windows $PROOF_HELPER_RELEASE_TAG"
echo
echo "- Target: x86_64-pc-windows-msvc"
echo "- Signing status: ${signing_status}"
echo "- Signing status: Unsigned preview"
echo "- Proof-assets descriptor: proof-assets-ownership-destination-v2-preprod-9fac96b-g3a"
echo "- Proof-assets download route: public HTTPS (GitHub release asset), size and hashes pinned in the app descriptor"
echo
echo "Do not describe this as a general Windows end-user release until Authenticode signatures, a public proof-assets download route, and local Windows release-build validation are complete."
} > dist/proof-helper-windows-x64/release-notes.md

- uses: actions/upload-artifact@v4
- uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
with:
name: proof-helper-windows-x64
path: dist/proof-helper-windows-x64/*
Expand All @@ -210,17 +208,19 @@ jobs:
name: Draft GitHub release
needs: build-windows
runs-on: ubuntu-22.04
permissions:
contents: write
steps:
- uses: actions/download-artifact@v4
- uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4
with:
name: proof-helper-windows-x64
path: release-artifacts

- name: Create GitHub Release
uses: softprops/action-gh-release@v2
uses: softprops/action-gh-release@3bb12739c298aeb8a4eeaf626c5b8d85266b0e65 # v2
with:
tag_name: ${{ inputs.tag }}
name: Proof Helper Windows ${{ inputs.tag }}
tag_name: ${{ env.PROOF_HELPER_RELEASE_TAG }}
name: Proof Helper Windows ${{ env.PROOF_HELPER_RELEASE_TAG }}
draft: ${{ inputs.publish_release != true }}
prerelease: true
body_path: release-artifacts/release-notes.md
Expand Down
7 changes: 7 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,9 @@ experiments/wasm-prover/patches/*
!experiments/wasm-prover/patches/computeh-scoped-coset-tables.patch
!experiments/wasm-prover/patches/uints-constant-fold.patch
!experiments/wasm-prover/patches/computeh-parallel-transforms.patch
!experiments/wasm-prover/patches/mpc-phase1-parallel-update.patch
!experiments/wasm-prover/patches/mpc-phase1-parallel-codec.patch
!experiments/wasm-prover/patches/mpc-phase2-parallel-initialize.patch
!experiments/wasm-prover/runtime/**
!experiments/wasm-prover/fault/**
!experiments/wasm-prover/scripts/**
Expand All @@ -90,3 +93,7 @@ experiments/wasm-prover/web/*
/docs/ux-review-landing-and-claim-flow.md
/contracts/ownership-verifier/testdata/*-review.md
.vercel/

# Local Go build outputs.
/mpc-ceremony
/workflowhelper
2 changes: 1 addition & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ coherent). This file only covers the mechanics.

```bash
pnpm install # repo root: installs Biome + lefthook, registers git hooks
bash scripts/bootstrap-vendor.sh # required: vendors gnark with the local ProveStream patch
bash scripts/bootstrap-vendor.sh # required: vendors gnark with the reviewed local patches
```

Never run plain `go mod vendor`; it drops the hand-applied patch. Use the
Expand Down
5 changes: 4 additions & 1 deletion apps/proof-helper-desktop/scripts/stage-windows-release.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,10 @@ const manifest = {
package_version: packageJson.version,
tauri_config_version: tauriConfig.version,
cargo_version: cargoVersion,
signed: process.env.PROOF_HELPER_WINDOWS_SIGNED === "1",
// Staging does not Authenticode-sign or verify artifacts. A future signed
// release path must derive this field from signature verification, never
// from operator input.
signed: false,
sidecar: {
name: path.basename(sidecarPath),
target: TARGET,
Expand Down
61 changes: 61 additions & 0 deletions apps/proof-helper-desktop/scripts/stage-windows-release.test.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import { execFileSync } from "node:child_process";
import { createHash } from "node:crypto";
import fs from "node:fs";
import fsp from "node:fs/promises";
import path from "node:path";
import { afterEach, expect, test } from "vitest";

const tempDirs = [];

afterEach(() => {
for (const dir of tempDirs.splice(0)) fs.rmSync(dir, { recursive: true, force: true });
});

test("stages Windows artifacts as unsigned even when the environment claims signing", async () => {
const root = await fsp.mkdtemp("/tmp/proof-helper-windows-stage-");
tempDirs.push(root);
const app = path.join(root, "apps", "proof-helper-desktop");
const bundle = path.join(root, "bundle");
await fsp.mkdir(path.join(app, "src-tauri"), { recursive: true });
await fsp.mkdir(bundle, { recursive: true });
await fsp.writeFile(path.join(app, "package.json"), '{"version":"0.2.2"}\n');
await fsp.writeFile(
path.join(app, "src-tauri", "tauri.conf.json"),
'{"version":"0.2.2","productName":"Proof Helper"}\n',
);
await fsp.writeFile(
path.join(app, "src-tauri", "Cargo.toml"),
'[package]\nname = "proof-helper-desktop"\nversion = "0.2.2"\n',
);

const installer = path.join(bundle, "Proof Helper.msi");
const sidecar = path.join(root, "proof-tool-x86_64-pc-windows-msvc.exe");
const out = path.join(root, "out");
await fsp.writeFile(installer, "installer-bytes");
await fsp.writeFile(sidecar, "sidecar-bytes");

execFileSync(
process.execPath,
[
path.resolve("scripts/stage-windows-release.mjs"),
"--repo-root",
root,
"--tag",
"proof-helper-desktop-v0.2.2-windows-preview.1",
"--bundle-dir",
bundle,
"--sidecar",
sidecar,
"--out-dir",
out,
],
{ env: { ...process.env, PROOF_HELPER_WINDOWS_SIGNED: "1" } },
);

const artifact = "proof-helper_0.2.2_windows_x64.msi";
const bytes = await fsp.readFile(path.join(out, artifact));
const digest = createHash("sha256").update(bytes).digest("hex");
expect(await fsp.readFile(path.join(out, `${artifact}.sha256`), "utf8")).toBe(`${digest} ${artifact}\n`);
const manifest = JSON.parse(await fsp.readFile(path.join(out, "proof-helper-windows-release-manifest.json"), "utf8"));
expect(manifest.signed).toBe(false);
});
Loading