Every KCC1 covenant lives inside an ordinary Kaspa P2SH output. There is no new output type and no new address format. This page defines the exact bytes on both sides of that envelope; the rest of the series depends on knowing where the covenant program R comes from.
Background: Pay-To-Script Hash (P2SH).
The locking side
A KCC1 covenant instance uses script public key version 0 with this script:
OP_BLAKE2B OP_DATA_32 Blake2b(R) OP_EQUAL The script is 35 bytes; every byte is fixed except the hash. Blake2b(x) here means unkeyed BLAKE2b with a 32-byte output, no key and no salt.
The consequence:
An unspent covenant output exposes only
Blake2b(R). Not the program, not its state, not even the fact that it is a covenant.
You cannot read a covenant’s state off the chain until somebody spends it. Indexers therefore recover state from spending transactions, and a covenant that wants to inspect a sibling has to be handed that sibling’s bytes as witness data.
The hash function split
KCC1 uses two different hash functions, and they must not be confused:
| Where | Function | Why |
|---|---|---|
| P2SH redeem-script commitment (this page) | BLAKE2b | Fixed by Kaspa’s existing P2SH consensus rules |
| Everything KCC1 defines itself - template hashes, dispatch tags, virtual-element commitments | BLAKE3, 32-byte output | KCC1’s own choice, written Hash(x) in the spec |
So Hash(R) and Blake2b(R) are different values over the same bytes, and the spec means different things by them.
The unlocking side
The spending input’s signature_script must be push-only and must have this logical layout:
PushArguments(arguments)
[OP_DATA_4 dispatch_tag]
PushMinimal(R) Three rules govern it:
- The arguments come first, in parameter order, as described in The Value ABI.
- The dispatch tag is omitted for a program with exactly one entrypoint, and required for a program with two or more. See Entrypoints & Dispatch.
PushMinimal(R)must be the final push.
The counter contract has one entrypoint taking no arguments, so its signature script is the minimal possible case - just the program:
Note that those 58 bytes are pushed as data. They are not executed during signature-script evaluation. The leading 08 is a byte of the counter’s state, not an opcode being run.
Execution: two passes over one stack
The engine runs signature_script and script_public_key back to back on a shared stack, then runs the revealed program.
Two things follow from this structure:
- After the hash check, the stack holds exactly the arguments (and the dispatch tag, when present). The program was consumed to become the code being run. That is why the argument encoding in The Value ABI is defined in terms of stack elements.
- The revealed program must leave a truthy value on the stack for the spend to be valid, like any redeem script.
The commitment covers all of R
Blake2b(R) covers every byte of R - logic and state.
Change a single byte of embedded state and
Blake2b(R)changes, even though the template is untouched.
This is the enforcement mechanism: state and address are bound together, so committing to one commits to the other. It is why a covenant can compute its successor’s address.
It also means a covenant instance’s address changes on every transition. Stateful covenants do not have stable addresses, and tooling must not assume one.
Conformance vector
KCC1 gives a minimal worked example. For the one-byte program R = 51 (OP_1):
Blake2b(R) = ce57216285125006ec18197bd8184221cefa559bb0798410d99a5bba5b07cd1d
scriptPublicKey.version = 0
scriptPublicKey.script = aa20ce57216285125006ec18197bd8184221cefa559bb0798410d99a5bba5b07cd1d87
signature_script = 0151 Note the signature script: 0151 is OP_DATA_1 followed by the byte 0x51. It pushes the one-byte redeem script as data - it does not execute OP_1 during signature-script evaluation.
Next
Next: The Value ABI, which defines how the typed values on the stack are encoded.