Kaspa Explained · Demo

What a proof can't prove

Kaspa's Toccata upgrade checks ZK proofs (math proofs a computer can verify without redoing the work) on-chain. Pick what to prove, then run it.

Ask a centralized server

Check the proof yourself

Why this happens, and how it maps to Kaspa

Kaspa's Toccata hard fork added OpZkPrecompile (KIP-16, Status: Active), an opcode that checks a proof against a chosen proof system, initially Groth16 and RISC0-Succinct. The opcode confirms a proof verifies against a given verifying key and public inputs. It says nothing about where those public inputs came from.

Proving "I know a secret number" is exactly that kind of self-contained check: everything the proof needs is already in its own inputs. Proving "the real price of BTC right now" asks the proof to vouch for a fact about the outside world, something no arithmetic check can do by itself. That gap needs an external anchor instead, such as a light client, a finality certificate, or a reporter set with something to lose.

The reason this beats asking a server for the same yes/no answer: a server's answer is only as good as your trust in that server, and checking it means either taking its word or getting access to whatever private data it based the answer on. A verified proof is checked against Kaspa's own public ledger, by anyone, using only the verifying key and the public inputs already on that ledger. Nothing about the app's private internal state has to be exposed for the check to work. One public ledger, many apps, and each app's own state stays its own.

So how does a real fact from outside the chain, a price, a bridge event, a sports score, ever get into a proof's public inputs? Someone has to attest to it: sign a statement saying "this is the value," and hand the app that signature instead of the raw fact. The proof can then check the signature the same way it checks any other public input. That's an oracle. It's not a cryptographic trick that removes the trust problem, it's a trust decision: pick a signer, and believe them.

Kaspa's L1 does not ship an oracle system. KIP-16 (Status: Active) added the verifier opcode, wired to Groth16 and RISC0-Succinct. What an app builds on top, which oracle to trust, how many signers to require, what happens when they disagree, is an application-level choice, not something the protocol decides for you. Whether that arrangement is trustworthy is a question about the signer, never a question the on-chain math can answer.

Kaspa's 10 blocks per second means a signed attestation can land on-chain and start accumulating proof-of-work in about a second, instead of waiting on a slower chain's block time. That's a real property: it shortens how long an app has to sit on stale data before acting on it. It does not touch who you're trusting. A faster chain gets you a wrong price faster, exactly as easily as a right one.

Sources: KIP-16, OpZkPrecompile, docs.kaspa.org/programmability. No proof is actually computed here; this toy names what a proof would and would not cover, and no network requests are made.