Kaspa’s Covenants opcodes and Covenant IDs are consensus primitives. They say what a script is allowed to inspect and enforce. They deliberately say nothing about how a covenant should lay out its data.
That last part is a convention problem, and conventions are what the KCC (Kaspa Covenant Conventions) documents standardize. Without them, every covenant is a private binary format that only its own author’s tooling can read.
That line — what the network enforces versus what programs merely agree on — is the most useful one to keep straight, and it is why this series is split into two groups in the sidebar. Break a consensus rule and your transaction is rejected. Break a convention and your covenant still works; it just becomes unreadable to everyone else’s tooling.
This page establishes the mental model. The pages after it fill in the detail, each building on the one before.
The one idea everything rests on
A covenant program is a script that contains its own state as literal bytes, and whose address is the hash of those bytes.
That single sentence has a surprising consequence, and it is the mechanism behind every covenant on this page:
Because the script is the state, and the address is the hash of the script, a covenant can compute the exact address its successor must have — by taking its own bytes, splicing in the new state, and hashing the result.
The script does not need to “remember” anything. It reconstructs its own future from bytes it can already see.
Building up to it
1. P2SH hides the script until you spend
A Pay-To-Script-Hash output commits only to a 32-byte hash. Nobody can read the script from the chain while the output is unspent. To spend it you must reveal the script (the redeem script) and it must hash to the committed value. See P2SH Script Format.
Call that revealed redeem script R. Throughout the KCC documents, R means the entire covenant program.
2. The program carries its state
R is not just logic. It begins with a run of data pushes holding the covenant’s current values, followed by the code that acts on them:
Spending the output reveals all of it — so the running script can read its own current state directly out of its own bytes.
3. Splice new state into the same logic
The logic bytes are the template. Keep them, swap the state, and you have the successor program R_next. Here is the same contract compiled with count = 8:
4. The address follows from the bytes
R_next hashes to a different value than R, so it has a different address:
blake2b(R) = e9c4ef0278b3d9f5d6d234ae89e2e38f30462fb9b9eeb32ed7caa76625552706
blake2b(R_next) = c4497fd43fe47ddf0a83fb58130ad999ce587f0e00a52a5b380c3f51fa6fd511 The script computes that second hash while it is running, wraps it in the standard P2SH script public key, and requires that one of the transaction’s outputs pays to exactly it. If the spender tries to pay anywhere else, the script fails.
That is the whole covenant loop:
The consumed instance validates its own successor. Consensus never has to understand the contract — the script does the checking.
Vocabulary
KCC1 fixes these terms, and the rest of this series uses them precisely.
| Term | Meaning |
|---|---|
| Covenant | A spending program that inspects transaction context and restricts how this transaction’s outputs may be spent later |
Covenant program (R) | The complete executable byte string, including every embedded value and its current encoded state. The P2SH redeem script |
| Covenant instance | A UTXO locked to a covenant program. Identified uniquely by its outpoint |
| Transition | A transaction consuming one or more covenant instances and creating zero or more continuations |
| Continuation | An output the consumed instance accepts as its successor |
| Template | What is left of R when the state range is removed — an ordered prefix and suffix |
Two distinctions worth internalizing early, because they are easy to blur:
- A program is bytes; an instance is a UTXO. Several UTXOs can hold the identical program.
blake2b(R)therefore identifies a contract-in-a-state, not a coin. - A template is shared by every state a contract can be in. It is the closest thing to “the contract’s identity” that pure script can express — which is why so much of KCC1 is about hashing and authenticating templates.
Where consensus helps: Covenant IDs
Reconstructing the successor address proves the next output is correct. It does not, on its own, prove that the UTXO you are spending descends from a legitimate origin rather than from a lookalike someone else deployed.
KIP-20 solves that in consensus. A Covenant ID is an optional 32-byte value on a UTXO marking it as a member of a lineage, and a covenant binding on an output names the input authorizing it. Consensus itself enforces that continuations inherit their parent’s Covenant ID, and the OpCov* and OpAuth* opcodes let a script query that structure directly.
So the two halves divide cleanly:
- The script proves the successor’s contents are correct.
- Consensus proves the successor’s lineage is correct.
Covenant IDs are covered in depth in Covenant IDs & Bindings.
What the KCC documents standardize
None of the above changes consensus rules. The KCCs are conventions layered on top of primitives that already exist.
| Document | Scope |
|---|---|
| KCC1 | Byte layouts and ABI: value encodings, entrypoints and dispatch tags, the P2SH envelope, state and templates, lineage roles, virtual elements |
| KCC2 | How a program ABI declares who controls a covenant, so observers can answer “whose is this?” |
| KCC20 | A fungible-token covenant surface: required state prefix, transfer interface, and a published descriptor |
KCC1 is deliberately independent of any source language or compiler. SilverScript is the reference compiler that produces programs in this shape, and every hex example in this series is real output from it.
How to read this series
The pages are ordered so each one only relies on the pages before it, and grouped by whether they describe a network rule or a convention.
Consensus — enforced by the network. True of every covenant, whatever conventions it follows.
| # | Page | What it adds |
|---|---|---|
| 1 | Covenant Opcodes | The full opcode surface a covenant can call |
| 2 | Covenant IDs & Bindings | KIP-20 lineage — how a covenant gets a forgery-proof identity |
Conventions — the KCC documents. Agreements about byte layout that make covenants interoperable.
| # | Page | What it adds |
|---|---|---|
| 3 | The P2SH Covenant Envelope | How R is committed to, revealed, and executed |
| 4 | The Value ABI | How typed values become bytes — the alphabet everything else is written in |
| 5 | Entrypoints & Dispatch | How one program exposes several callable branches |
| 6 | State, Templates & Continuations | How state is carved out of R and spliced back in |
| 7 | Template Views & Virtual Elements | Partial state mutation, and committing to data too large to embed |
| 8 | Leaders & Delegators | Coordinating a transition across several covenant inputs |
| 9 | Control Principals | KCC2 — declaring who controls a covenant |
| 10 | KCC20 Fungible Tokens | The whole stack applied to a real token standard |
If you only read two, read Covenant IDs & Bindings and State, Templates & Continuations — one from each half, and together they cover the concepts that most often trip people up.
Status
KCC1, KCC2, and KCC20 are all Draft. SilverScript is explicitly experimental and its authors recommend testnet-10 only for now. Where the current compiler and the draft specs differ, this series says so on the page where it matters.
The primitives underneath them are not draft — they are active on mainnet as of the Toccata hard fork. On-chain adoption is charted live at covenant transactions, covenant outputs, and covenant UTXO count.
Working examples
Runnable covenant code, useful for seeing the primitives exercised end to end:
covenant_id.rs— Covenant ID genesis and continuation, in rusty-kaspacovenants.rs— introspection-based covenants, in rusty-kaspaforced_recipient.py— building a covenant transaction with the Kaspa Python SDKcounter.py— a stateful covenant walked through real transitions on testnet-10- SilverScript example contracts — including
kcc20.silandkcc20-minter.sil - The SilverScript KCC20 book — a full walkthrough of the token and minter contracts
Specifications
| Spec | Covers |
|---|---|
| KCC1 | Covenant definition, concepts, byte layouts and ABI |
| KCC2 | Control principal references in program ABIs |
| KCC20 | Fungible token covenant specification |
| KIP-10 | New transaction opcodes for enhanced script functionality |
| KIP-16 | New transaction opcodes for verifiable computation (the ZK precompile) |
| KIP-17 | Covenants and improved scripting capabilities |
| KIP-20 | Covenant IDs |
See also the KIPs reference and SilverScript.
Prior art
Covenants are a long-running idea in the UTXO world, and much of the design vocabulary comes from Bitcoin research:
- BIP-119 (
OP_CHECKTEMPLATEVERIFY), BIP-345 (OP_VAULT), BIP-347 (OP_CAT) - CAT Protocol — covenant-based fungible and non-fungible tokens
- Covenant use cases and UTXOs.org
- Awesome OP_CAT
- ZK covenants and verifiable programs (vprogs)