Every KCC1 covenant lives inside an ordinary Kaspa P2SH output. No new output type, no new address format. This page pins down the exact bytes on both sides of that envelope, because the rest of the series depends on knowing precisely where the covenant program R comes from.
Background: P2SH Script Format and Pay-To-Script Hash.
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 35 bytes, and every one of them is fixed except the hash. Blake2b(x) here means unkeyed BLAKE2b with a 32-byte output, no key and no salt.
The consequence is worth stating plainly, because it shapes everything downstream:
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 mixing them up is a common early mistake:
| 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.
Our counter contract has one entrypoint taking no arguments, so its signature script is the minimal possible case — just the program:
The critical subtlety: 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 shape, and both matter later:
- 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 is total
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 not a limitation to work around; it is the enforcement mechanism. It is precisely why a covenant can pin down its successor’s address: state and address are rigidly bound, so committing to one commits to the other.
It also means a covenant instance’s address changes on every transition. Address reuse is not a thing for stateful covenants, and any tooling that assumes a stable address will be wrong immediately.
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. The distinction is the same one as above, just small enough to see whole.
Next
You now know where R comes from and what the stack looks like when it starts running. Next: The Value ABI, which defines how the typed values on that stack are encoded.