Cryptographic voter verification and ballot integrity for U.S. elections — replacing trust assumptions with mathematical proofs.
VoteChain is a two-layer open protocol. The verification layer answers "is this voter eligible?" using cryptographic credentials on a permissioned ledger (no PII on-chain, no biometric mandates). The ballot integrity layer (Election Web Protocol) provides the chain of custody from cast to tally — encrypted ballots, append-only logs, and verifiable decryption proofs.
Everything is published for transparency and critique.
┌──────────────────────────────────┐ ┌──────────────────────────────────┐
│ Layer 1: Verification │ │ Layer 2: Ballot Integrity │
│ (VoteChain PRD) │ │ (Election Web Protocol — EWP) │
│ │ │ │
│ • Permissioned verification ledger │ │ • Encrypted ballots (ElGamal) │
│ • ZK eligibility proofs │ │ • Append-only bulletin board │
│ • Nullifier-based uniqueness │ │ • Threshold decryption (t-of-n) │
│ • Fraud detection pipeline │ │ • Verifiable tally proofs │
└──────────────────────────────────┘ └──────────────────────────────────┘
│ │
└──────── Audit anchors (hash) ──────────┘
- Layer 1 checks four things: citizen, eligible, alive, not already voted — all via zero-knowledge proofs that never reveal identity.
- Layer 2 ensures cast-as-intended (Benaloh challenge), recorded-as-cast (Merkle inclusion proof), and counted-as-recorded (verifiable decryption).
| Path | Description |
|---|---|
src/pages/votechain/ |
Astro pages: landing, PRD, EWP spec, architecture, FAQ, assurance playbooks |
src/votechain-poc/ |
Browser-based proof of concept (credential issuance, ballot encryption, cast, verify, tally) |
src/votechain-poc/crypto/ |
Cryptographic primitives: blind Schnorr, ECIES, ECDSA, Shamir secret sharing |
workers/votechain-nodes/ |
Cloudflare Workers — three independent ledger nodes (federal, state, oversight) |
functions/ |
Cloudflare Pages Functions (Turnstile gate, session, replication proxy) |
tests/ |
Vitest test suite (13 files; run with npm test) |
docs/ |
Internal assurance playbooks |
docs/poc-physical-demo-hardware.md |
Physical-only demo topology, node layout, and budget planning |
PRD-VOTER-VERIFICATION-CHAIN.md |
Full VoteChain PRD (voter verification specification) |
PRD-VOTECHAIN-ELECTION-WEB-PROTOCOL.md |
Full EWP specification (ballot integrity) |
PLAN-VOTECHAIN-ASSURANCE.md |
Assurance planning document |
- Node.js >= 20 (< 23)
- npm >= 10
npm install
# Optional local config:
cp .env.example .env
# Ensure Git LFS is active for binary assets
git lfs install
git lfs pull
npm run dev # Start Astro dev serverOpen http://localhost:4321/votechain/ in your browser.
npm test # Run once
npm run test:watch # Watch modenpm run e2e:setupThe walkthrough now auto-starts a local Astro dev server (if needed), creates a local-scope election with multiple positions plus a referendum, and writes screenshots/logs under playwright-artifacts/.
playwright-artifacts/ is intentionally gitignored so test PNGs and logs from this flow are never accidentally committed.
To target a remote deployment instead of local:
BASE_URL=https://absurdityindex.org/votechain/poc npm run e2e:setupNotes:
- Production may require Turnstile/session unlock before
/setupcan be used. - Set
AUTO_START_DEV_SERVER=0if you want the script to fail instead of auto-starting local dev.
npm run build # Static build → dist/
npm run preview # Preview production build# Deploy to test project
npm run deploy:test
# Deploy to production project
npm run deploy:prodPages projects:
- Test:
votechain-test - Production:
votechain(votechain-dap.pages.dev)
Automated deploy pipeline: .github/workflows/pages-deploy.yml (GitHub Actions).
npm run typecheckThe three VoteChain ledger nodes are Cloudflare Workers. To run locally:
npx wrangler dev --config workers/votechain-nodes/federal/wrangler.toml
npx wrangler dev --config workers/votechain-nodes/state/wrangler.toml
npx wrangler dev --config workers/votechain-nodes/oversight/wrangler.tomlSee workers/votechain-nodes/README.md for API details and deployment instructions.
By default, the POC runs entirely in the browser and does not require any live nodes.
If you want the Monitor/Trust pages to read from Workers nodes by default, set one of:
PUBLIC_VOTECHAIN_WORKERS_BASE(template with{role}placeholder)PUBLIC_VOTECHAIN_FEDERAL_NODE_URL,PUBLIC_VOTECHAIN_STATE_NODE_URL,PUBLIC_VOTECHAIN_OVERSIGHT_NODE_URL
If you deploy on Cloudflare Pages and want the browser POC to replicate events into your Workers ledger, configure Pages env/secrets:
VOTECHAIN_FEDERAL_NODE_URL,VOTECHAIN_STATE_NODE_URL,VOTECHAIN_OVERSIGHT_NODE_URLVOTECHAIN_FEDERAL_WRITE_TOKEN,VOTECHAIN_STATE_WRITE_TOKEN,VOTECHAIN_OVERSIGHT_WRITE_TOKEN
The POC runs entirely in the browser (localStorage state, no server required). It implements simplified versions of the protocols:
- Setup — Configure a new election bundle with a guided form builder (option pools -> bound questions) and anchor both manifest + form definition to the ledger
- Vote — Generate credentials, encrypt a ballot, cast it
- Verify — Check your receipt (signature + Merkle inclusion + anchor)
- Dashboard — Inspect the bulletin board, VCL events, fraud flags, and tally
- Trust Portal — Independently verify all public keys and proofs
- Lookup — Find a ballot by its hash
- Monitor — Watch the bulletin board for equivocation
For fully physical demos where every role is on a separate device, use:
It includes:
- Required node roles for compact (15-node) and full-fidelity (20-node) physical layouts.
- Exact board layout narrative with VLAN boundaries.
- USD estimate ranges by hardware option (refurb/new Raspberry Pi vs x86 mini-PC).
POC setup flow and ledger anchoring notes are documented in docs/votechain-poc-setup-ledger-flow.md.
| Experience VoteChain | Voting Kiosk |
|---|---|
![]() |
![]() |
| Oversight Dashboard | Receipt Verification |
![]() |
![]() |
- Astro — static site generation
- Tailwind CSS v4 — styling
- TypeScript — type safety
- @noble/curves — secp256k1 elliptic curve operations
- Cloudflare Workers + Durable Objects — ledger nodes
- Vitest — test runner
See CONTRIBUTING.md, CODE_OF_CONDUCT.md, CHANGELOG.md, and the issue templates under
./.github/ISSUE_TEMPLATE for contribution entry points.
See SECURITY.md for the vulnerability disclosure policy.
See RELEASING.md for test and production deployment workflow.



