Inspiration

Every time a student applies for a job, internship, or university program, they are forced to hand over their entire academic transcript — exposing failed electives, retaken courses, personal struggles, and grades in subjects completely unrelated to the role they are applying for.

The recruiter's actual question is deceptively simple: "Does this person meet the minimum CGPA threshold?"

Yet the current system answers that question by over-exposing everything. Students have no control. Transcripts are printed, emailed, and stored on third-party systems with no privacy guarantees whatsoever.

This felt fundamentally broken to us. The moment we learned about Midnight Network and its native support for zero-knowledge computation at the protocol level, we knew exactly what to build. If a student could mathematically prove they meet a threshold — without disclosing the raw number behind it — that would be a genuine paradigm shift in academic privacy.

Cygnus was born from that conviction.

What it does

Cygnus is a privacy-preserving academic credential wallet built on the Midnight Network. It enables three roles to interact with academic credentials in a way that is simultaneously verifiable and privacy-safe:

  • 🏛️ University (Issuer): The university inputs a student's grade and a minimum eligibility threshold. A cryptographic commitment (hash) of the grade is signed off-chain by the institution's attestation server and published on the Midnight PreProd ledger. The raw grade is never stored on the blockchain.

  • 🎓 Student (Holder): The student enters their private grade as a secret input (witness) to a local Zero-Knowledge circuit. The circuit verifies that the private grade matches the on-chain commitment $\text{Hash}(\text{grade}) = \text{commitment}$ and satisfies the eligibility threshold $\text{grade} \geq \theta$. A ZK proof is generated entirely on the student's machine via a local Docker proof server and submitted to the Midnight ledger. The grade never leaves the browser.

  • 🏢 Employer (Verifier): The recruiter queries the on-chain credential status using just the Credential ID and receives a single cryptographically-backed verdict: ELIGIBLE or NOT ELIGIBLE. Zero raw data. Zero privacy violation.

How we built it

Cygnus is a full-stack Web3 application spanning four workspaces in an npm monorepo:

1. Smart Contract — Compact on Midnight Network

We wrote the core ZK circuit in Compact, Midnight's purpose-built smart contract language. The contract exposes three circuits: issueCredential (stores the commitment hash on the public ledger), proveEligible (accepts a private grade witness and verifies the threshold condition), and checkEligibility (reads the on-chain verification status). Compact treats all function arguments as private witnesses by default, requiring explicit disclose() annotations for any data that should appear on the public ledger.

2. Attestation API — Express + TypeScript

We built an off-chain attestation server that the university panel calls to sign credentials using HMAC-SHA256 with an institutional secret key. This creates a trust anchor binding the university's identity to the credential hash, preventing students from fabricating their own commitments.

3. Frontend DApp — React + Vite + Midnight Connector

The React DApp integrates with the Midnight Lace Chrome wallet extension via the official DApp Connector API, allowing users to sign and submit transactions from their browser wallet. We designed a modern glassmorphism dark-themed UI with three separate panels for each role.

4. Deployment — create-mn-app + PreProd Testnet

We scaffolded the deployment workspace using create-mn-app and successfully deployed the contract to the Midnight PreProd public testnet at contract address 53fe8fbc9c9cf5477266d6bf60e8be66525016d55a5e69bddf2a5bf2c3d6b3e1.

Challenges we ran into

1. Compact compiler constraints with public ledger access

The hardest bug: Compact treats all inputs as private by default. Passing a credentialId argument directly into a Map.lookup() ledger operation caused a compiler error — you cannot perform a public ledger read with an unverified private input without explicit disclosure. The fix was wrapping the value in disclose(credentialId), teaching us a deep lesson about Compact's privacy model.

2. Docker container DNS resolution failure

Our proof server container needed to download ZK parameter files from srs.midnight.network at startup. Inside Docker Desktop on macOS, the container's DNS resolver was failing silently. We diagnosed this by inspecting container logs and resolved it by manually injecting Google's public DNS servers (8.8.8.8, 8.8.4.4) directly into docker-compose.yml.

3. Wallet sync state corruption

After an interrupted sync session, the Midnight wallet SDK's local LevelDB commitment tree ended up in an inconsistent state, throwing values inserted non-linearly into dust commitment tree; expected index 1075523, received 1075544. The fix was clearing the .midnight-wallet-state cache folder and re-syncing from genesis.

4. Testnet block sync latency

Syncing a fresh wallet against the full Midnight PreProd block history took over 20 minutes on first run, as the SDK replays every block from genesis to reconstruct the shielded UTXO set.

Accomplishments that we're proud of

  • ✅ Successfully deployed a Compact ZK smart contract to the public Midnight PreProd testnet.
  • ✅ Built a complete end-to-end privacy flow from institutional signing → local ZK proof generation → on-chain verification across three separate user roles.
  • ✅ Integrated the Midnight Lace wallet extension into a production-quality React DApp using the official DApp Connector API.
  • ✅ Implemented a real cryptographic trust model using HMAC-SHA256 institutional signatures to prevent credential forgery at the source.
  • ✅ Navigated and resolved three distinct infrastructure-level bugs in a brand new blockchain toolchain with minimal community resources available.

What we learned

  • Zero-knowledge is not just cryptography — it is a design philosophy. Compact forced us to think about privacy boundaries at the circuit level, not as an afterthought. Explicitly annotating what is public (disclose()) versus what stays private reshaped how we reason about data flow.

  • The two-token model on Midnight (NIGHT / DUST) is elegant. Transaction fees live in the transparent NIGHT layer, while shielded operations happen in the DUST layer. Even the act of generating a ZK proof does not link your identity to the operation on the public ledger.

  • Privacy is not a feature — it is a fundamental human right in credential systems. Seeing the entire workflow run end-to-end — with an employer receiving a verified ELIGIBLE result while never touching the raw grade — made the value proposition feel very real.

What's next for Cygnus

  • 🎓 Multi-credential support: Extend beyond CGPA to certifications, research publications, attendance records, and scholarship eligibility.
  • 🏫 Institution onboarding: Build an institution key registry so verifiers can confirm the institutional origin of any credential without trusting a centralized server.
  • 📱 Mobile wallet integration: Adapt the DApp for mobile as the Midnight Lace wallet expands to mobile platforms.
  • 🌐 Mainnet deployment: Migrate from PreProd to production once Midnight Network launches its public mainnet, with a full security audit of the Compact circuits.
  • 🤝 University partnerships: Pilot with real academic institutions to build a production-grade credential issuance pipeline integrated with existing student information systems.
Share this project:

Updates

Submission history