The puzzle at the center of Midnight
Every blockchain has the same basic promise: nobody can secretly change the record, because everyone can see it. That's what makes it trustworthy. But "everyone can see it" is also the obvious problem if you want any kind of privacy. If your age, your balance, or your identity has to sit in public for the network to verify it, you haven't built a private system at all.
Midnight is built to solve exactly this puzzle, and the two tools that make it possible are much simpler than they sound: a hash function, and a cryptographic commitment. This article explains both in plain language, then shows exactly how Midnight uses them, with everything sourced to Midnight's own official documentation so you can verify it yourself.
What a hash function actually is
Think of a hash function as a machine that takes anything you feed into it, a word, a number, an entire document, and crushes it down into a short, fixed-length code that looks like random gibberish. Feed it the same input twice, and you get the exact same gibberish both times. Feed it something even one letter different, and the output looks completely unrelated to the first one. And critically, there's no way to run the machine backward: looking at the gibberish alone tells you nothing about what went in.

This isn't a Midnight-specific idea. It's one of the most well established tools in computer security. One of the hash functions Midnight relies on, SHA-256, is a formally standardized algorithm published by the United States' National Institute of Standards and Technology, which defines exactly how it turns any message into a 256-bit digest [1].
Midnight's smart contract language, Compact, gives developers two built-in hash functions, and the distinction between them matters:
persistentHashuses SHA-256 and is guaranteed to produce consistent results even as the Midnight protocol itself is upgraded over time. Midnight's documentation states this is the one to use for anything stored in the ledger or used for authentication [2].transientHashis optimized to be cheaper to compute inside a zero-knowledge circuit, but it comes with no guarantee of staying consistent across future protocol upgrades, so it's meant only for short-lived, temporary checks within a single interaction [2].
So far, this solves one problem: it lets you take something and turn it into a short, unforgeable fingerprint. But on its own, a hash function has a weakness, and understanding that weakness is what makes commitments make sense.
The weakness hashing alone doesn't fix
Imagine a contract needs to check whether you're over 18, and all it stores on-chain is the hash of your birth year. That sounds private. But a birth year only has a few hundred possible values. Anyone curious could simply hash every plausible birth year themselves and compare the results against what's on-chain, and they'd find your real birth year almost instantly. The hash function worked exactly as designed, it's just that "exactly as designed" isn't enough when the input itself is easy to guess.
Midnight's own security documentation names this directly: hash functions are most useful for data that already has a unique fingerprint and isn't easily derivable by a malicious actor on its own [2]. A birth year, a yes-or-no flag, a small balance, none of those qualify. That's exactly the gap cryptographic commitments are built to close.
What a cryptographic commitment actually is
A commitment works like a sealed envelope. You write something down, seal it inside, and hand the sealed envelope to someone else. They can hold onto that envelope, and later you can open it to prove what you originally wrote. Two things make this trustworthy: the envelope can't be swapped out later with a different message, and nobody can see through the envelope while it's sealed.

A commitment does exactly this with cryptography. Instead of hashing your value alone, you combine it with a second, random, secret value, called a salt, before hashing. Midnight's documentation explains why this matters precisely because of the weakness described above: pairing a value with a sufficiently random salt makes the simple value impossible to guess, even if there were only a handful of possibilities to begin with, unless the random salt itself is also guessed [2].
Midnight's official documentation names the exact two guarantees a commitment is supposed to give you, using these specific terms:
Hiding: the commitment reveals nothing about the original value. An observer looking at it on-chain cannot determine what you committed to.
Binding: once you've created a commitment, you cannot change your mind about the value afterward. The commitment permanently locks you to what you originally put in [2].
Compact provides this as a built-in pair of functions, mirroring the hash functions above:
persistentCommitis a SHA-256-based commitment meant for anything that needs to remain valid long-term and survive protocol upgrades.transientCommitis a cheaper, circuit-efficient version meant only for temporary hiding within a single interaction [2].
How commit and reveal actually works
Midnight's documentation walks through this with a simple two-step pattern. First, you commit to a value along with a random salt, and store only the resulting commitment publicly. Later, when you need to prove what that value was, you provide the same value and the same salt again, the contract recomputes the commitment from scratch, and checks it against what's already on-chain. If they match, your claim is verified. If they don't, you've proven nothing, because you couldn't have produced a matching commitment without the original value and salt [2].
This is also why commitment values don't need the extra privacy wrapper Compact normally requires for sensitive data. Because the random salt makes the committed value unrecoverable on its own, Midnight's compiler treats a properly salted commitment as already safe to store publicly [2].
One detail worth taking seriously: Midnight's own documentation warns that you should never reuse the same random salt across two different commitments. Doing so lets an outside observer link those two commitments together, which quietly breaks the privacy the whole scheme was supposed to provide [2].
A clever extra trick: nullifiers
Hashing and commitments combine to solve one more problem that comes up constantly in private systems: how do you stop someone from spending the same private resource twice, like reusing a digital coin or a one-time credential, without revealing which specific resource they used?
Midnight's answer is a nullifier, a one-way hash derived from a secret that uniquely identifies a resource without revealing anything about which resource it was. Every time something is spent or consumed, its nullifier gets recorded publicly in a set. Before anything can be spent, the contract checks that its nullifier isn't already in that set. Because the nullifier reveals nothing about its origin, outside observers can see that something was spent, but never which thing [2].
Why the same idea gets a different "label" each time
If you've looked at any Midnight example code, you'll notice the same pattern of hashing a secret together with a short text string, something like "nullifier-domain" or "commitment-domain", before the actual value. This is called domain separation, and it exists to stop one specific attack: using the exact same secret for two unrelated purposes, which could otherwise let someone trick one part of a contract into accepting a hash meant for something else entirely. Midnight's documentation recommends giving every distinct purpose its own label for exactly this reason [2].
Putting it all together
None of this exists for its own sake. It's the literal mechanism behind some of the things that make Midnight useful in the first place:
Proving you're over a certain age without revealing your birthdate, by committing to your birth year once and later proving the committed value satisfies an age check.
Proving you own something, like a credential or a score on a leaderboard, by storing a commitment to a secret key as your "ownership proof," and later proving you still hold that same secret [3].
Preventing the same private credential, vote, or coin from being used twice, through nullifiers that mark something as spent without revealing which specific item was spent.
In every one of these cases, the pattern is identical: take something private, run it through a hash or a commitment, publish only the result, and later prove you know the original input without ever showing it. That's the entire trick behind how a public blockchain can still protect what you don't want to share.
Sources
FIPS PUB 180-4, Secure Hash Standard (SHS) : U.S. National Institute of Standards and Technology, the official specification defining SHA-256 and its properties
Smart contract security : Midnight official documentation, covering hash functions, commitment schemes, the hiding and binding properties, nullifiers, domain separation, and the randomness reuse warning, all cited directly throughout this article
Writing a contract : Midnight official documentation, the canonical example showing
persistentHashused to derive an ownership commitment from a secret key
For the most current details on Compact's cryptographic primitives, including any future additions or changes, check the official documentation directly rather than relying on any article, including this one, as a permanently up to date reference.

Replies
Discussion
Join the discussion
Sign in with Google to reply. You stay on this article while you sign in.
No replies yet
Sign in with Google to start the discussion.