After the recently shared kcc-01 draft, which introduces common covenant concepts, byte layouts and Program ABI conventions, and with the goal of progressively helping the definition process of kcc-20, we (as a group of ecosystem individuals) felt the need to call for convention the concept of ownership.
Identity and ownership are and will continue to be central pieces of many covenants. You can think of a simple example: “this address owns a kcc-20 token”, which effectively means that the token covenant program has an area reserved for a reference to its owner.
Or you can think of a more complex example: “this pool covenant owns a kcc-20 token”. The owner is no longer a person’s address, but could be one exact covenant program identified by a program_hash, or a continuing covenant lineage identified by a covenant_id (or both).
Question: As a user, how can my wallet know which covenant UTXOs declare an owner that I recognize, whether that is a direct reference to one of my keys or an indirect reference through another covenant that I control?
Before we continue, I must place boundaries on this topic. kcc-02 is not trying to define authentication mechanisms (that will likely be a follow-up KCC) but only to make ownership references discoverable and understandable.
It is important to make this distinction, and it is easy to mix them. Knowing that a value represents the owner does not yet tell us which entrypoints require its authorization, or how this authorization must be provided.
There is also a small terminology challenge. “Owner” is very natural for a token, but becomes a little less natural when speaking about an administrator, a minter, a treasury member or another application-defined role.
That’s why from now on I’ll refer to a control principal: the entity associated with such a role. But feel free to continue reading “control principal” as “owner”. The broader name is only here so the same standard can also serve use cases where ownership is not the exact relationship.
The different possible principal profiles we identified so far, by order of plausible popularity, are:
- a direct Schnorr or ECDSA public key.
- one continuing covenant lineage, possibly with template checks, naturally useful for a stateful covenant.
- one exact covenant program, naturally useful for a stateless covenant.
- other community-defined profiles like
pq-xmas-tree.
There already is one challenge for public-key ownership. A direct Schnorr public key is represented by 32 bytes, while a compressed ECDSA public key is represented by 33 bytes.
In the effort of making principal references uniform in length, it is proposed to create two profiles: p2pkh-schnorr/v1 and p2pkh-ecdsa/v1. In short, the principal reference is a 32-byte hash commitment to the public key. The actual public key and the signature would be provided at runtime.
Additionally, since a covenant program is as a complete executable byte string. If it eventually supports multiple authentication profiles, the different corresponding verification branches must be part of that program.
In this context, it might already rely on state roughly looking like this:
{
"owner": "<32-byte principal reference>",
"owner_kind": 0
}
The Program ABI can then explain that owner is a principal reference and that owner_kind selects how it should be interpreted.
We also should have in mind that there can be multiple principal references in one covenant, for example a multisig covenant or a treasury fund. A plausible state could be:
{
"owners": ["<principal reference A>", "<principal reference B>"]
}
For the sake of simplification, we’re not going further here into cases where every owner can use a different profile. How lists of principals should be exposed is one of the areas where the proposal would benefit from discussion.
Proposal
TL;DR: The program ABI must emit the principals-reference declarations, so they are readable by all network observers (think: wallet) later..
This is an early draft, and I’m sharing it now to avoid defining “ownership” in isolation, that could make the wallet infrastructures fragmented.
Collaboration and discussion are welcome. Product promotions/mentions or LLM copy-paste are not.
Possible future Argent syntax
Here is a possible future syntax showing where this could lead. This syntax is not part of KCC-02.
Declare two identities: one is a direct Schnorr public key, while the other can dynamically select between several compatible 32-byte principal references.
state State {
identity<p2pk_schnorr> owner;
identity<p2pkh_schnorr | p2pkh_ecdsa | covenant_id | program_hash> my_mixed_owner;
}
If we later go into the realm of authentication, here is a possible syntax that plays well with the previous one:
state State {
identity<p2pkh_schnorr | covenant_id | program_hash> owner;
}
// ...
entry method() emits one State {
// authenticate the owner
authenticate(owner);
become State(self.state);
}
// Or mutate the owner, for example in a transfer method:
entry transfer(
// next_owner is expected to respect State.owner's shape
// here, it cannot be a direct p2pk_schnorr public key
next_owner: identity like owner
) emits one FixedToken {
authenticate(owner);
State next_state = {
owner: next_owner,
};
become State(next_state);
}
Again, authenticate(owner) belongs to a possible follow-up authentication standard. KCC-02 is only trying to establish the smaller common foundation that makes such a feature possible later: knowing which values represent owners or other control principals, and how those values should be interpreted.