Skip to content

Introduction

Midnight Compact Lab is a browser-based integrated development environment for Compact — the smart contract language of the Midnight blockchain. You write, test, and deploy privacy-preserving contracts entirely in your browser, with no local installation required.

The Lab handles the Compact compiler, local simulation runtime, ZK proof visualization, and Midnight network connectivity so you can focus exclusively on writing contract logic.

What is Compact?

Compact is a domain-specific language designed for writing smart contracts on the Midnight blockchain. Its defining feature is built-in zero-knowledge proving: contract logic runs privately on the user's device and only a cryptographic proof is submitted on-chain. Public state is updated without ever revealing the private inputs that produced the proof.

This model makes Compact uniquely suited for applications requiring selective disclosure — proving a condition is true without revealing the underlying data.

Note

Compact compiles to ZK circuits. Each circuit function in your contract becomes a provable computation. The compiler version used in Compact Lab is >=0.20.

Quick Start

No sign-up is required for the playground. Open Compact Lab and:

  1. Choose a starter template from the Templates panel — or start from a blank file.
  2. Write your Compact contract in the editor. Syntax errors are highlighted inline.
  3. Click Simulate to run the contract locally and inspect circuit output.
  4. When ready, connect your wallet and deploy to Midnight Testnet.

Interface Overview

The Compact Lab interface is split into three main zones:

Editor Panel

Center canvas where you write Compact source code. Features syntax highlighting, bracket matching, and inline error markers.

Output Panel

Displays compiler output, circuit statistics (constraint rows, k-parameter), witness declarations, and simulation results.

File Explorer

Manage multiple .compact files per project. Templates are pre-loaded as individual files.

Keyboard Shortcuts soon

A full keyboard shortcut reference is coming soon. In the meantime the editor supports standard code editor bindings (save, undo/redo, find, comment toggle).

File Management soon

Multi-file project support, import/export of .compact files, and local persistence are on the roadmap.

Contract Structure

Every Compact contract begins with a language pragma and a standard library import. At the top level you declare ledger state, witnesses, a constructor, and one or more circuit functions.

Counter.compact
pragma language_version >= 0.20;

import CompactStandardLibrary;

// ── ledger state (public, on-chain) ──────────────
export ledger count: Counter;

// ── private witness ──────────────────────────────
witness secretKey(): Bytes<32>;

// ── initialises on-chain state ───────────────────
constructor() {
  count.increment(0);
}

// ── provable transition ──────────────────────────
export circuit increment(): [] {
  count.increment(1);
}

Ledger State

Ledger variables hold persistent, public state stored on the Midnight blockchain. They are declared at module scope using the ledger keyword.

export ledger count:    Counter;     // auto-incrementing integer
export ledger owner:    Bytes<32>;   // 32-byte hash (e.g. public-key hash)
export ledger sequence: Counter;     // monotonic sequence number
export ledger state:    State;       // user-defined enum

Warning

Ledger variables are always public. Never store private data directly in a ledger variable. Use witness declarations and the disclose() pattern instead.

Circuits

A circuit is a function whose execution generates a ZK proof. When you call an exported circuit from a Midnight DApp, the proof is computed client-side and submitted on-chain without revealing the private inputs.

export circuit post(): [] {
  assert(state == State.VACANT, "Board is occupied");
  owner = disclose(persistentHash<Bytes<32>>(localKey()));
  state = State.OCCUPIED;
  sequence.increment(1);
}

The return type [] means the circuit returns nothing publicly. A circuit can also return public values, e.g. [Uint<32>].

Witnesses & Privacy

A witness declaration names a private value that the user supplies at proof-generation time. This value never touches the blockchain — only the proof that something valid was provided is recorded.

// declares that the user will provide a 32-byte secret key
witness secretKey(): Bytes<32>;

// or: a key derived from the local wallet
witness localKey(): Bytes<32>;

Inside a circuit you can use witness values freely. The compiler ensures they cannot "leak" into public state unless explicitly wrapped in disclose().

The disclose() Pattern

disclose() is the gate between private and public. It marks an expression as intentionally made public, which allows it to be written into a ledger variable.

// ✓ safe — only the HASH of the secret key is public
owner = disclose(persistentHash<Bytes<32>>(secretKey()));

// ✗ compile error — can't assign a witness directly to ledger state
// owner = secretKey();

Two hashing builtins are available:

  • persistentHash<T>(value) — produces the same hash across multiple transactions for the same input. Use for ownership proofs.
  • transientHash<T>(value) — produces a unique hash per transaction. Use for one-time commitments.

Built-in Types

TypeDescription
CounterAuto-incrementing ledger integer (call .increment(n))
Bytes<N>Fixed-length byte array of length N
Uint<N>Unsigned integer with N-bit precision
Booleantrue / false
FieldPrime field element (raw ZK circuit value)
Maybe<T>Optional value — none<T>() or some<T>(val)
ZswapCoinPublicKeyA Midnight wallet public key
Vector<N, T>Fixed-length array of N elements of type T

Simulating Contracts soon

The simulation panel lets you invoke circuits locally, inspect ledger state changes, and view compiler-generated statistics — all without connecting to any network.

Circuit Output soon

After compilation, the output panel will display circuit statistics in this format:

Compilation successful

circuit increment  (k=10, rows=29)
circuit pause      (k=12, rows=41)

witness secretKey: shielded ✓

k is the circuit depth parameter and rows is the number of constraint rows. Lower is faster and cheaper to prove.

Privacy Inspector soon

The Privacy Inspector is a visual tool for understanding exactly what your ZK circuits reveal on-chain. It colour-codes each expression in your contract — green for private (stays on device), red for disclosed (goes on-chain).

This panel is currently under development and will ship in a future release.

Deploying to Testnet soon

Full step-by-step deployment guides for Midnight Testnet and Mainnet are coming as the network moves toward stable releases.

Deploying to Mainnet soon

Warning

Smart contract bugs on Mainnet can result in permanent, irreversible loss of funds. Always complete a thorough Testnet validation and an independent audit before deploying to Mainnet.

Using Templates

Templates are pre-written Compact contracts that demonstrate common patterns. To load a template, open the Templates panel from the sidebar, hover a card, and click Use Template. The contract is loaded directly into the editor.

Available Templates

Private Counter

A counter with owner-gated pause functionality. Demonstrates Counter ledger type, witness ownership proofs, and assert guards.

PrivateCounter.compact

Bulletin Board

A single-slot message board where only the original poster can take down their message. Demonstrates State enum, disclose(), and sequence counters.

BulletinBoard.compact

ZK Loan

A privacy-preserving loan application that proves creditworthiness without revealing the underlying score. Based on the official Midnight example.

ZkLoan.compact

Token Transfer

soon

A simple shielded token that moves balances privately between ZswapCoinPublicKey addresses.

Wallet Setup soon

Compact Lab will support connecting a Midnight-compatible wallet to sign and submit transactions. A step-by-step wallet configuration guide will be published once the Midnight wallet SDK reaches a stable API.

Tip

For now you can use Compact Lab fully in simulation mode without connecting a wallet. A wallet is only required for on-chain deployment.

FAQ

Do I need to install anything?

No. Compact Lab runs entirely in your browser. The Compact compiler and simulation runtime are bundled as WebAssembly modules.

Is my code stored anywhere?

Contract code you write is processed locally in your browser. We do not store or transmit your source files unless you use an explicit share feature.

Which Compact version is supported?

Compact Lab currently targets the Compact compiler at version ≥ 0.20. The active compiler version is shown in the output panel after compilation.

Can I use the Lab without a Midnight wallet?

Yes. Simulation mode is fully functional without a wallet. A wallet is only needed when deploying to Testnet or Mainnet.

Where can I find official Compact language documentation?

See the official Midnight documentation at docs.midnight.network/compact.