KIP-16 OpZkPrecompile verifying Groth16 and RISC0 proof data in a Kaspa transaction script
KIP-16 Explained: Native ZK Proof Verification on Kaspa
May 28, 2026
KIP-21 active-lanes sparse Merkle tree connecting application lanes to one Kaspa header commitment
KIP-21 Explained: Partitioned Sequencing Commitments for Scalable Proving
May 29, 2026

KIP-20 Explained: Covenant IDs and Consensus-Traced Lineage


KaspaBuy
July 16, 2026

KIP-20 adds an optional 32-byte covenant_id to Kaspa covenant outputs and their resulting UTXOs. Consensus accepts that identity only as a valid continuation or a correctly derived genesis. The result is stable, indexable lineage across state transitions, but covenant scripts must still enforce every application-specific rule governing their authorized outputs.

Key takeaways

  • A covenant-bound output declares both a 32-byte covenant ID and the input that authorizes its creation.
  • Continuation outputs inherit the same ID from the spent covenant UTXO; genesis outputs must derive it from a unique outpoint and the authorized initial outputs.
  • The binding is committed by transaction and signature hashes, while the UTXO set commitment carries the resulting ID.
  • New introspection opcodes expose input IDs, authorized outputs, covenant participants, and output bindings without ancestor-transaction witnesses.
  • Consensus-traced lineage prevents arbitrary labels from being created, but it does not validate the application’s state-transition logic on its own.

Why did Kaspa need covenant IDs?

Transaction introspection can let a script constrain the transaction that spends it. However, a stateful application also needs to answer a persistent identity question: does this new UTXO belong to the same covenant instance as the one being spent?

Without a native identifier, a script may need parent or grandparent transactions as witness data, then reproduce canonical serialization and hashes to establish ancestry. The KIP-20 specification identifies the resulting witness overhead and execution-layer complexity as the problem it is designed to remove.

The merged KIPs PR #35 calls the mechanism “consensus-traced covenant lineage.” That phrase is precise: consensus tracks a stable ID through UTXO creation and spending. It is not a general account model and does not turn every UTXO with matching application data into a member.

How do continuation and genesis work?

Each covenant-bound output contains a CovenantBinding with an authorizing_input index and a covenant_id. When that authorizing input spends a UTXO carrying the same ID, the new output is a continuation. This gives a direct lineage edge from the consumed state to its authorized successor.

If the input does not already carry that ID, the output is treated as genesis. Consensus groups genesis outputs by authorizing input and proposed ID. It then derives the ID with domain-separated BLAKE2b-256 over the input’s unique previous outpoint and an ordered encoding of the authorized initial outputs, including their indices, amounts, and script public keys.

The covenant binding itself is excluded from the hash to avoid self-reference. Because an outpoint cannot repeat, an arbitrary party cannot choose an existing covenant identity for unrelated genesis outputs. If the calculated digest does not equal the declared ID, consensus rejects the transaction.

What does the data model commit to?

KIP-20 extends supported transaction outputs with the optional covenant binding and extends UtxoEntry with an optional ID. Version-zero transactions cannot carry the new binding; the specification requires transaction version 1 or later for outputs that use it.

The binding participates in the transaction ID and signature hash. The ID stored in a UTXO participates in the UTXO commitment. The specification also accounts for a covenant UTXO as carrying 32 additional bytes for storage mass. These details prevent the identity from being a wallet-only annotation that nodes could disagree about.

The relationship with KIP-16’s ZK verification opcode is complementary. A covenant could use a proof to authorize a state transition and use a covenant ID to preserve the instance’s lineage. A valid proof does not create the lineage rule, and the ID does not prove the off-chain computation.

Which introspection opcodes are added?

The specification defines a precomputed covenant context so repeated script operations do not rescan the entire transaction. Its opcodes include:

  • OpInputCovenantId to read the ID of a spent UTXO, or a zero hash when absent;
  • OpAuthOutputCount and OpAuthOutputIdx to enumerate continuation outputs authorized by one input;
  • OpCovInputCount, OpCovInputIdx, OpCovOutputCount, and OpCovOutputIdx to enumerate transaction participants sharing one covenant ID;
  • OpOutputCovenantId and OpOutputAuthorizingInput to inspect a declared output binding, including genesis outputs.

Consensus validates genesis membership, but genesis outputs are deliberately excluded from the continuation-oriented shared contexts. A contract that initializes state must inspect and constrain its outputs using the appropriate genesis-aware operations rather than assuming they appear in continuation lists.

What can developers build with stable lineage?

A one-to-one covenant can preserve a singleton state UTXO through repeated updates. A one-to-many covenant can authorize a bounded set of successor outputs. More complex asset-like transitions can use a leader-and-delegator pattern in which one input validates the full many-to-many transition while other inputs prove that the leader was correctly selected.

These are patterns, not automatic standards. Kaspa Script has no general loops, so a contract validating multiple outputs needs an explicit upper bound and unrolled checks. Developers should test zero, one, maximum, and one-over-maximum output cases. They should also reject unexpected extra covenant outputs and ensure amount, script, state, and authorization relationships are all covered.

KIP-21 approaches state from another direction. The partitioned sequencing commitment guide describes how application-lane activity can be anchored efficiently. KIP-20 identifies a covenant instance inside the UTXO set; KIP-21 commits ordered lane activity across chain blocks.

Limitations: what a covenant ID does not prove

A matching ID proves consensus-recognized lineage, not business correctness. The spending script must verify that each successor has the expected script public key, state commitment, value constraints, and transition shape. If a script authorizes an unsafe output, consensus can correctly preserve the ID of an unsafe state.

The ID also does not guarantee uniqueness of live state. A one-to-many transition may intentionally create several UTXOs with one ID. Singleton behavior exists only if the covenant script enforces exactly one continuation. Nor does a stable ID supply an indexer, user interface, data availability, audit, or recovery path.

Finally, PR #35 added a consensus specification and cited a reference implementation history. A specification merge is not proof that every wallet, SDK, explorer, or node release supports the field. Software must use the transaction version and activation rules of the target network.

Frequently asked questions

Can someone copy a covenant ID onto an unrelated output?

They can propose the bytes, but consensus accepts them only as a same-ID continuation or a genesis value correctly derived from the unique authorizing outpoint and authorized outputs.

Does every UTXO need a covenant ID?

No. The field is optional. Ordinary outputs can have no covenant binding and continue to use the non-covenant path.

Does KIP-20 replace KIP-17 transaction introspection?

No. KIP-20 is designed to work with KIP-17. KIP-20 supplies lineage and covenant-specific context; KIP-17 supplies broader transaction introspection primitives.

Source and verification note

This article is based on kaspanet/kips PR #35, merged on May 28, 2026, and the maintained KIP-20 specification. Field widths, version rules, genesis hashing, opcode names, and accounting details above come from that primary specification. Implementers should verify current rusty-kaspa code, network activation parameters, and serialization libraries before constructing transactions.

Related Posts

KIP-20 Explained: Covenant IDs and Consensus-Traced Lineage
This website uses cookies to improve your experience. By using this website you agree to our Data Protection Policy.
Read more