This version doesn’t incorporate the authorisation abstraction for KL signature constraint yet
Kudos is an application that defines kudos denomination interface and describes how different denominations work. Kudos denominations might have some meaning assigned to them (e.g., money, trust, etc), but we will ignore the meanings here.
This is a revised version of the kudos application, it aggregates the results of the discussions from these posts:
- Shielded Kudos: Issue, Burn, Transfer (with Conditional Receive), Swap
- Shielded Kudos Pt. 2: Verifying Constraint Authorship
- Shielded Kudos Pt. 3: KL constraints
- Shielded Kudos Pt. 4: DL examples
High-level description
This kudos application allows creating kudos of multiple denominations. Kudos can be issued, burned, conditionally transferred, or swapped for other denominations or resources of unrelated kinds. Denominations are created dynamically and can contain arbitrary constraints. The kudo application logic ensures that the basic and denomination constraints are enforced.
Components
1. Kudo
This application operates on kudos. Kudos are resources that are characterised by the following resource fields:
- logic: the main kudos logic (KL)
- label: encodes a denomination logic (DL). Can include additional parameters expected by the DL such as the issuer’s identity
- value: encodes the owner’s identity
Currently, identities are represented by public keys.
2. The main kudos logic KL
The main kudo logic KL verifies some universal constraints and ensures that the relevant logics such as DL and receive logic are verified, when required.
Consume
- The DL is triggered: there is a resource R_{DL} in the same action s.t.
R_DL.logic = self.label.dl_vk
Create
- The DL is triggered: there is a resource R_{DL} in the same action s.t.
R_DL.logic = self.label.dl_vk
- The receive logic is triggered [1]:
1. There is a created resource R_{receive} in the transaction s.t.:Signature.Verify(Sig,R_receive.logic, self.value.owner) = True
3. Denomination logics DL
The kudo application expects to have multiple kudos denominations. Each denomination has its own logic that is carried by an ephemeral resource. Each kudo resource specifies its denomination by encoding the relevant denomination logic. The KL then verifies that the DL of each kudo resource is verified in the same action.
A denomination might set additional constraints on the kudo resource of the corresponding denomination, for example, require what certain fields must contain.
Denomination logic itself is carried by an ephemeral resource.
DL example
This denomination logic authorises all actions by verifying signatures. The issuance/burn is authorised by the denomination owner, transfer is authorised by the kudo owner.
The kudo additional structure specified by this DL:
- label: includes the issuer’s pk
- value: includes the owner’s pk
Consumed kudo r
- Ephemeral:
- verify a signature issued by the denomination owner signing the list of cms + nfs of the action:
Signature.Verify(issuer_pk, cms + nfs, Sig) = True
- verify a signature issued by the denomination owner signing the list of cms + nfs of the action:
- Persistent:
- verify a signature issued by the kudo owner signing the list of cms + nfs of the action:
Signature.Verify(owner_pk, cms + nfs, Sig) = True
- verify a signature issued by the kudo owner signing the list of cms + nfs of the action:
Created kudo r
- Ephemeral:
- verify a signature issued by the denomination owner signing the list of cms + nfs of the action:
Signature.Verify(issuer_pk, cms + nfs, Sig) = True
- verify a signature issued by the denomination owner signing the list of cms + nfs of the action:
Proving system inputs
- Instance: commitments, nullifiers (nothing extra)
- Witness: resource objects (includes issuer’s pk), signatures
4. Receive logics
Receive logics are associated with users and describe when sending to this user is allowed. Receive logics must be authorised by the user they belong to and are triggered when a transfer is initiated. Receive logics are carried by ephemeral resources of the receive kind. Their verification is currently triggered by KL.
Non-trivial receive logic example
This receive logic only allows receiving tokens of non-zero quantity of the listed assets.
Receive resource fields:
- label: includes the identity of the user it belongs to
- logic: receive logic
Constraints:
There is a created kudo ‘r’ in the same action s.t.:
r.owner = self.label.owner
(checking that the kudo is created for the person whose receive logic is currently being checked)r.kind() is in allowedKinds
. List of allowed kinds is hardcoded in the logic in this example. We can imagine that it is something like this:allowedKinds = [apple, orange, banana]
(the list contains specific kinds instead of letters)r.quantity > 0
The constraint is triggered for all receive logic resources (we only create ephemeral ones to trigger the logic by design, but we can just not check it since it doesn’t seem to allow any invalid behaviour)
Transaction functions
Issue and burn kudos
We start with issuing and burning kudos since they are pretty similar to each other and are the simplest action possible.
- On the diagram, the grey resources correspond to kudos resources of denomination
#n
and the green resources represent the denomination#n
authorisation logic. - KL requires a resource with a DL from the label to be present in the same action. The DL resource verifies the issuance conditions specific to that denomination.
- The same idea works for burning, except that now we consume a persistent resource instead of creating a persistent resource.
- The denomination resource is ephemeral and has zero value, we only need to trigger the logic verification.
Transferring kudos with conditional receive
To allow specifying receive policies, we need to require a receive logic to be verified. This implies we need a resource that carries that logic. It cannot be a part of DL since it isn’t associated with the denomination, it is associated with the receiver. Receive logic presence requirement must be a part of the kudos logic (i.e., required for all denominations), otherwise the malicious sender can always create a denomination that doesn’t require it and send it to the desired receiver.
- As in the issue/burn case, we need to trigger the corresponding DL
- To bind the receive authorisation logic to the action, KL requires that there is a resource in the same action that is associated with the specified receiver’s pubkey
- To make sure the authorisation logic is indeed created by the receiver, the receive authorisation resource must contain a signature over the authorisation logic. This signature must be verified by KL
- As for DL, receive resource only triggers the logic and therefore can be ephemeral and zero value
Swap
Swapping kudos (to kudos of other denominations or completely different resources) is not limited by the application design and works the same way as swapping any resources work.
Further work
Receive logic distribution and safety
The user is expected to share the signed version of their receive logic with whoever is going to send them the assets. It raises a few questions:
- how to preserve the privacy of the receive logics and only reveal it to relevant parties / only reveal relevant parts of the logic
- how to update logics and how to control which versions are used
- how can multiple logics be maintained
We discussed these questions here and a bit here. For now we assume the simplest version: receive logics are distributed as needed, creating a new receive logic doesn’t invalidate the old one.
Validating created ephemeral kudos
The main discussion is here
What is the role of ephemeral resources in the kudos application? They are used exclusively for balancing. At the same time, if users are allowed to send ephemeral resources to other users, we must trigger their receive logic. If we don’t do that, it is still possible for users to “spam” other users with ephemeral kudos. At the same time, triggering receive logic for ephemeral kudos has no value and is costly. Sending ephemeral kudos shouldn’t be allowed.
The problem here is that we can’t just fail a transaction that contains ephemeral kudos since we do need them for balancing. My proposal is to prohibit sending ephemeral resources to anyone but the owner of the balancing consumed resources. This removes the incentive to spam since the user can only spam themselves. To enforce that, we must have the balancing consumed resource in the same transaction (which is somewhat limiting).
What if there are multiple consumed resources with different owners that correspond to such a created ephemeral resource? I don’t have a good answer for that question. Remember that the only situation when we need to create ephemeral kudos is burning, which is a somewhat special use case.
- Do we want to allow burning multiple kudos of different owners at once?
- Perhaps we can then call the receive logic for the group identity combining the owners of consumed resources (how to work with such an identity is out of scope of this post)
What I see as the best solution is to somehow bind the created ephemeral kudos to the creator of the kudo to remove the incentive.
Another idea I had is to remove ownership concept from ephemeral resources but this unfortunately doesn’t help since the resources themselves still are sent to someone. We need to make sure that someone can either control what they receive or the creator doesn’t have the incentive to spam the possible receiver.
Other open questions
- Authorisation abstraction of signature verification in KL:
- Expected action size for different logics
if we find another way to constrain sending ephemeral kudos, this constrain can be checked for persistent resources only ↩︎