Shielded Kudos Pt. 4: DL examples

In this post I’ll provide two examples of DL logics. They are not meant to describe the most common use cases, these are just two examples that are meant to highlight the programmability features of the kudos application.

Example one: named token

Function Condition
Issue/Burn Can only be done by a certain entity
Transfer/Swap Allowed only if 2% of the transferred value is sent to the issuer, i.e., if the sender and receiver are not issuer, then there must be another resource with quantity 0.02q that is sent by the same owner and received by the receiver

Example two: Loyalty Points

Function Condition
Issue Can only be issued by a certain entity. Each token has an associated expiration date
Burn No extra constraints
Burn for reward The owner can issue a burn intent claiming reward from the issuer for burning their loyalty points. Only for non-expired tokens.
Transfer/Swap No extra constraints

A note on burn-for-reward mechanics

While working on this example, I came up with an idea of burn/issue-for-reward mechanics. I described my thoughts in more details here. This is not a crucial question for this example, so I don’t want to think too much on how to implement it the best way. A simple option to implement it on the DL side is to always verify that there is some extra logic (intent) associated with the burn. For “simple” burns, the intent is always satisfied.

Could you pls clarify the constraints, witnesses and instances of the DL? And what’s in labels and values?

If the KL and DL description is complete, it would be helpful to see concrete transaction examples. For instance, for a named token issue transaction/action, how many resources are needed (including padding and dummy resources) in practice, and how they are constrained, and correlated.

1 Like

Example one: named token

Kudo structure

  • label: includes the issuer’s pk

The categories below describe the kudo resource being verified. The DL carrying resource is always created and 0 quantity.

Consumed kudo r

Ephemeral:

  • verify a signature issued by the owner signing the list of cms + nfs of the action: Signature.Verify(issuer_pk, cms + nfs, Sig) = True

Created kudo r

Persistent:

  • there is a created kudo r' of the same denomination with r'.owner = r'.issuer, r'.quantity = 0.02 * r.quantity

Ephemeral:

  • verify a signature issued by the owner signing the list of cms + nfs of the action: Signature.Verify(issuer_pk, cms + nfs, Sig) = True

  • Instance: commitments, nullifiers (nothing extra)

  • Witness: resource objects (includes issuer’s pk), signatures

Thanks for posting the details. I have a few questions mostly to ensure I understand correctly.

  1. It implies that denomination resources are always ephemeral and have a quantity of 0. Does “consumed/created” and “ephemeral/persistent” refer to the status of kudo resources? Is self.quantity kind of ambiguous if it refers to kudo quantity while self is a denomination resource?
  2. Is the label for denomination resources empty?
  3. The consumed ephemeral constraints describe issuance checks. Are consumed persistent constraints missing to indicate persistent resource consumption via Signature.Verify(owner_pk, cms + nfs, Sig) = True?
  4. Are you charging 2% to the sender’s or receiver’s quantity? The constraint r.quantity = 0.02 * self.quantity applies to created persistent resources, meaning sender.quantity = receiver.quantity + 0.02 * receiver.quantity and the transferred value is based on receiver’s.
  5. Ephemeral created resources are constrained by Signature.Verify(issuer_pk, cms + nfs, Sig) = True. Does this imply only the issuer can burn these resources?
  6. How many resources does the DL expect? I think three: the self denomination resource, the kudo resource, and an extra kudo resource sent to the issuer. Is it correct?

Yes, you are right! I accidentally wrote everything from the kudo perspective, not the DL resource perspective. I’ll edit the post to make it clearer.

I think in this case it can be empty or we can put some data in it for ensuring uniqueness. Might also put the issuer’s pk in it.

Transferring persistent resources doesn’t require issuer’s signature, and if it is a burn, the signature is already verified on the balancing ephemeral resource.

Yes, that is what I meant to say.

Not directly. If the user burning resources can somehow obtain the signature over these tags, they can do it too. But practically speaking I guess so

Yes, for this example it is at most 3 resources that are checked in the logic

Thanks for clarifying everything.

I mean transferring persistent resources(or consuming persistent resources) should require the owner’s signature, which seems to be missing?

Why should it be required?

How does an owner authorize kudo resource consumption? Is signature verification used, or are other methods employed? It depends on how you define the identity and authorization for the application.

1 Like

In this particular example the denomination allows any transfers as long as 2% goes to the issuer, so the owner doesn’t have extra control over the transaction in case they decide to delegate the token creation to a solver.

We can also introduce another example, a simple signature one, where issuance, burn, and transfer are authorised with the signature and the 2% rule doesn’t apply. Issue and burn are authorised by the issuer, transfer is authorised by the sender. This example in some sense is more practical.

1 Like

Got it. It seems there is no ownership in this example and anyone who knows the plaintext of resources can consume them.

Can we use this example for our first implementation instance so that we can use the signature for authorization?
Beside the DL examples, could you also share a simple receive logic example as it is mandatory?

1 Like

Signature authorisation token

The issuance/burn is authorised by the denomination owner, transfer is authorised by the kudo owner.

Kudo structure

  • 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

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

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

  • Instance: commitments, nullifiers (nothing extra)

  • Witness: resource objects (includes issuer’s pk), signatures

1 Like

Simple non-trivial receive logic example

Only allow receiving tokens of non-zero quantity of the listed assets.

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)

1 Like