Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
3 changes: 3 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
* text=auto eol=lf
*.tgz binary
*.wasm binary
27 changes: 20 additions & 7 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,29 @@ on:
workflow_dispatch:

jobs:
test:
node:
runs-on: ubuntu-latest
strategy:
matrix:
node: [18, 20, 22]
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: "20"
node-version: ${{ matrix.node }}
cache: npm
- run: npm ci
- run: npm test
- run: npm pack --dry-run

- name: Install dependencies
run: npm install

- name: Run tests
run: node test/test.js
browser:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 22
cache: npm
- run: npm ci
- run: npx --no-install playwright install --with-deps chromium
- run: npm run test:packed
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
node_modules/
*.tgz
npm-debug.log*
18 changes: 18 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Changelog

## 0.2.0

- Verify current `ZAP1_COUNT_BOUND_V2` bundles with mandatory leaf-count
binding.
- Gate historical `ZAP1_LEGACY_DUPLICATE_ODD` verification behind an explicit
caller option and the frozen anchor-height cutoff.
- Replace the unreproducible generated WASM artifact with auditable,
zero-runtime-dependency JavaScript.
- Reject malformed digests, ambiguous proof positions, oversized proofs,
unsafe leaf counts, impossible tree paths, missing schemes, internal-node
substitution, and silent legacy downgrade.
- Test Node 18, 20, and 22 plus a real Chromium ESM import.

Version `0.1.3` remains the historical March-May artifact. Version `0.2.0`
is post-window compatibility maintenance for current count-bound proof bundles.
It does not change the application period, amount, or deliverables.
33 changes: 33 additions & 0 deletions PROVENANCE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# Release provenance

## 0.2.0

The release source is the commit bearing the annotated repository tag `v0.2.0`.
The npm artifact must be built from a clean checkout of that tag.

The JavaScript BLAKE2b implementation in `src/blake2b.js` is derived from:

- repository: `Frontier-Compute/zap1`
- commit: `63448237dc13e9199303f37c995294b2a56132b1`
- path: `verify-widget/blake2b.js`
- source SHA-256:
`D31E528C51BEF4D98D9A8B5EEA64550018DCE47EAD9AF8D3AD5D301A791A2BCA`

The release file is not byte-identical to that source. Its SHA-256 is
`5546B1C22EB13F60E9F45C1B358CB4FDCD8CCC77C3F2E039BBC5E3C057D39FC5`.
The delta adds strict type, length, digest, proof, leaf-count, and historical
height validation (59 inserted lines and 7 removed lines); the BLAKE2b
compression and personalization core is unchanged.

`test/test.js` includes independent Python `hashlib.blake2b` boundary
vectors at 0, 1, 3, 127, 128, 129, 255, 256, 257, and 1024 bytes, with and
without the protocol personalization. The release gate also:

- rebuilds `dist/` from source during `prepack`;
- asserts the exact tarball allowlist;
- installs that tarball into a fresh project with scripts disabled;
- tests current and historical proof semantics in Node and Chromium; and
- runs the source suite on Node 18, 20, and 22 in CI.

Version `0.1.3` remains the historical March-May artifact. Version `0.2.0`
is post-window compatibility and verifier-hardening maintenance.
54 changes: 44 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,17 @@

[**Dashboard**](https://frontiercompute.cash/dashboard.html) | [npm](https://www.npmjs.com/package/@frontiercompute/zap1) | [GitHub](https://github.com/Frontier-Compute/zap1-js)

ZAP1 Merkle proof verification for JavaScript and TypeScript. WASM-powered BLAKE2b-256 with ZAP1 domain-separated personalizations.

Client-side verification of on-chain commitments. All cryptography runs in WebAssembly compiled from the `zap1-verify` Rust crate.
Zero-runtime-dependency ZAP1 Merkle proof verification for JavaScript and
TypeScript. The cryptographic primitive is auditable JavaScript with no native
or WASM loader.
The verifier supports current `ZAP1_COUNT_BOUND_V2` proof bundles and an
explicitly gated historical legacy profile.

This package verifies Merkle-bundle consistency against a supplied root. It
does not prove that an encrypted Zcash memo contains that root, and it does not
prove the truth of the event represented by a leaf. A transaction ID is a
recorded reference until transaction existence and memo binding are checked by
separate evidence.

## Install

Expand All @@ -24,12 +32,15 @@ npm install @frontiercompute/zap1
```js
import { verifyProof, parseBundle } from "@frontiercompute/zap1";

const res = await fetch("https://pay.frontiercompute.io/verify/075b00df.../proof.json");
const leafHash = "your_64_character_leaf_hash";
const res = await fetch(
`https://api.frontiercompute.cash/verify/${leafHash}/proof.json`
);
const raw = await res.json();
const bundle = parseBundle(raw);

const valid = await verifyProof(bundle);
console.log(valid ? "VERIFIED" : "FAILED");
console.log(valid ? "BUNDLE CONSISTENT" : "BUNDLE INVALID");
```

### Compute a leaf hash
Expand All @@ -56,30 +67,53 @@ const parent = await nodeHash(leftHex, rightHex);

| Function | Description |
|----------|-------------|
| `init()` | Preload the WASM module (called automatically on first use) |
| `init()` | Compatibility no-op; retained for 0.1.x callers |
| `computeLeafHash(type, payload)` | Compute leaf hash for PROGRAM_ENTRY or OWNERSHIP_ATTEST |
| `verifyProof(bundle)` | Verify a Merkle inclusion proof |
| `verifyProof(bundle, options)` | Verify V2; historical legacy requires `allowHistoricalLegacy: true` |
| `nodeHash(left, right)` | Compute a Merkle node hash |
| `commitRoot(rawRoot, leafCount)` | Bind a raw root to its positive leaf count |
| `parseBundle(json)` | Parse and normalize an API proof bundle |
| `EVENT_TYPES` | Array of all 18 ZAP1 event types |
| `EVENT_TYPES` | The 18 defined protocol event types |
| `LEAF_HASH_TYPES` | The 2 event types with client-side typed hash formulas |

Proof-path verification is event-type agnostic. Typed leaf reconstruction is
currently available only for `PROGRAM_ENTRY` and `OWNERSHIP_ATTEST`.

### Root schemes

- `ZAP1_COUNT_BOUND_V2`: default and required for current bundles. The
committed root binds `leaf_count`.
- `ZAP1_LEGACY_DUPLICATE_ODD`: accepted only when the caller sets
`{ allowHistoricalLegacy: true }`, the bundle labels itself legacy, and the recorded
anchor height is at or below the frozen historical cutoff. A positive
`leaf_count` and an exact duplicate-odd proof shape are mandatory.

Missing counts, unknown schemes, malformed hashes, invalid proof positions,
and out-of-window legacy bundles fail closed.
When present, envelope metadata must use `protocol: "ZAP1"` and
`version: "2"` for either root scheme; the legacy label describes the root
construction, not an envelope-version downgrade.

## Personalizations (protocol constants)

| Context | Value (16 bytes) |
|---------|-----------------|
| Leaf hash | `NordicShield_\x00\x00\x00` |
| Node hash | `NordicShield_MRK` |
| Root commitment | `NordicShield_RTK` |

## Protocol

See [ONCHAIN_PROTOCOL.md](https://github.com/Frontier-Compute/zap1/blob/main/ONCHAIN_PROTOCOL.md) for the full ZAP1 specification.
See [ONCHAIN_PROTOCOL.md](https://github.com/Frontier-Compute/zap1/blob/main/ONCHAIN_PROTOCOL.md)
for the deployed protocol description. The document distinguishes bundle
verification, transaction existence, encrypted-memo binding, and event truth.

## Related Packages

| Package | What it does |
|---------|-------------|
| [@frontiercompute/zcash-ika](https://www.npmjs.com/package/@frontiercompute/zcash-ika) | Zcash + Bitcoin signing via Ika 2PC-MPC |
| [@frontiercompute/zcash-mcp](https://www.npmjs.com/package/@frontiercompute/zcash-mcp) | MCP server for Zcash (22 tools) |
| [@frontiercompute/zcash-mcp](https://www.npmjs.com/package/@frontiercompute/zcash-mcp) | MCP server for Zcash |
| [@frontiercompute/openclaw-zap1](https://www.npmjs.com/package/@frontiercompute/openclaw-zap1) | OpenClaw skill for ZAP1 attestation |
| [@frontiercompute/silo-zap1](https://www.npmjs.com/package/@frontiercompute/silo-zap1) | Silo agent attestation via ZAP1 |

Expand Down
Loading
Loading