Witnesses on Midnight: How Private Data Enters a Public Ledger Without Being Seen
witnesses

Witnesses on Midnight: How Private Data Enters a Public Ledger Without Being Seen

Witnesses are how Midnight lets your contracts use private data without ever exposing it on-chain. Instead of passing sensitive inputs publicly, data is injected locally at execution time, used inside a zero-knowledge circuit, and then disappears, leaving only a proof behind.

Mechack Elie (8pro)
Mechack Elie (8pro)
·March 31, 2026·4 min read·27 views
#witnesses#midnight#private#ledger

The Thesis

You can’t build private applications if every input is public.

Midnight solves this by separating where data is used from where data is stored.

Witnesses are the mechanism that makes that possible:

  • Private data stays local

  • Computation happens in a circuit

  • The network only verifies the result

No leakage. No exposure. Just proof.

Technical Architecture

Midnight extends a Substrate-based execution environment with a zero-knowledge circuit model, where smart contracts (written in Compact) define logic, but not all data.

Some data is intentionally missing.

That missing piece is filled at execution time through witnesses.

A witness is not a function in the traditional sense. It’s a declaration:

witness secretKey(): Bytes<32>;

There is no implementation in the contract.

The contract only defines:

  • what it needs

  • what type it expects

The actual value is injected at runtime from the DApp layer (TypeScript), just before proof generation.

This creates a split execution model:

  • On-chain → deterministic logic + verification

  • Off-chain → private data provisioning

What a Witness Actually Does

They allow your circuit to access private data without publishing it.

The flow looks like this:

You call:

contract.callTx.post("Hello")

The circuit executes locally.

At some point, it needs a value:

localSecretKey()

That call doesn’t resolve on-chain.

It jumps to your TypeScript implementation.

The Bridge Between Contract and Reality

Here’s what the contract says:

witness localSecretKey(): Bytes<32>;

Here’s what your DApp provides:

  • A function implementation

  • Access to private state

  • A return value used inside the circuit

The circuit doesn’t know where the data came from.

It only knows:

“I asked for 32 bytes. I got 32 bytes.”

That value:

  • enters the ZK circuit

  • participates in computation

  • gets locked inside the proof

And then disappears.

Why Witnesses Exist

Consider a simple constraint:

You want to prove ownership of a key.

But:

  • you cannot reveal the key

  • you cannot store it on-chain

Without witnesses, you’re stuck.

With witnesses:

  • the key is fetched locally

  • used inside the circuit

  • never exposed

The proof confirms:

“This user knows a valid key”

Without revealing:

“Which key”

That’s the entire point.

The Circuit Doesn’t Trust You

Here’s the part most people miss.

Witnesses are not trusted.

They run on the user’s machine.

That means:

Anyone can modify their witness implementation

So the contract must defend itself.

Example pattern:

  • Witness provides a secret key

  • Circuit derives a public key

  • Circuit compares it to stored state

If it doesn’t match:

  • the assertion fails

  • the proof becomes invalid

  • the transaction is rejected

The system doesn’t trust inputs.

It verifies outcomes.

The disclose() Boundary

By default, everything coming from a witness is private.

If you try to store it:

balance = getBalance(); // ❌

Compilation fails.

You must explicitly say:

balance = disclose(getBalance()); // ✅

This is not syntax noise.

It’s a security boundary.

The compiler tracks:

  • where private data flows

  • where it becomes public

Nothing is leaked accidentally.

Private State: Where Witness Data Lives

Witnesses don’t just return values.

They interact with private state stored locally.

This state:

  • lives in encrypted storage (LevelDB)

  • persists across sessions

  • never leaves the user’s machine

Each contract instance:

  • has its own private state

  • scoped by contract address

This allows:

  • user-specific secrets

  • per-contract isolation

  • persistent private logic

How Witnesses Fit Into the Transaction Flow

Now connect this to what you already learned about transactions.

The full lifecycle becomes:

  1. Circuit executes locally

  2. Witness is called → private data injected

  3. Circuit computes new state

  4. Unproven transaction is created

  5. Proof server generates ZK proof

  6. Proven transaction is submitted

  7. Network verifies proof

At no point:

  • is the private data broadcast

  • is it stored on-chain

  • is it visible to validators

It exists briefly:

  • in memory

  • inside the proving process

Then it’s gone.

The “Why” (Market Fit)

Most blockchains force a trade-off:

  • transparency vs privacy

Midnight removes that constraint.

Witnesses enable:

  • private identity systems

  • confidential financial applications

  • selective disclosure systems

They solve a real limitation:

You can’t build privacy-preserving applications if all inputs are public.

Witnesses make private inputs first-class citizens in smart contract execution.

Contextual Analysis

Compared to traditional models:

Ethereum

  • All inputs are public

  • Execution is replicated

Midnight

  • Inputs can be private

  • Execution is proven, not replayed

Witnesses are the missing abstraction that enables this shift.

Without them:

Midnight would behave like any other chain

With them:

It becomes a privacy-first computation layer

Roadmap & Hurdles

Witnesses introduce new responsibilities:

Strengths

  • Strong data privacy guarantees

  • Flexible off-chain data integration

  • Reduced on-chain exposure

Constraints

  • Developers must manage private state correctly

  • Security depends on proper validation logic

  • Debugging becomes less straightforward

The challenge is not tooling.

It’s mindset.

You are no longer writing fully deterministic on-chain programs.

You are designing:

  • partially local

  • partially provable

  • fully verifiable systems

Final Take

Your contract doesn’t need to know everything.

It just needs to prove enough.

Witnesses are how private data enters the system, does its job, and disappears without a trace.

Not hidden.

Not encrypted on-chain.

Never there in the first place.

Community

Discussion

Join the conversation

Connect your wallet to share your thoughts and engage with the community

No comments yet

Connect your wallet to be the first to comment!

BY

Written by

Mechack Elie (8pro)

Mechack Elie (8pro)

Web3 builder and open-source contributor, creating Eightblock, a wallet-based blogging platform for Cardano and blockchain education.

addr1qyej7l3mctvtqjvtxsr