Shielded kudos: authorisation abstraction

The main kudos application logic is designed to be constant[1]. Currently, it includes a signature verification constraint used to authorise receive logics, which might be seen as undesirable since it requires committing to a single signature scheme “forever”.

This post aims to discuss if it is possible and desirable to abstract this signature verification constraint away and how to do that.

What do we mean by authorisation abstraction?

The authorisation constraint we are talking about (in its current form) has two relevant properties:

  1. It is facing the users. Users provide the signature that is verified in the KL.
  2. Since KL is assumed to be constant, the chosen signature scheme is also assumed to be fixed.

What makes us not like this arrangement is the lack of choice and flexibility:

  1. The signature scheme is assumed to be used “forever”
  2. Users can’t choose the scheme they use to authorise their logic

We want the system to not depend on specific primitives and give the users an opportunity to choose their own security assumptions, so it might sound like a good idea to abstract this constraint away.

Abstracting something away here implies replacing it with some generic constraint bound to a separate constraint verified externally. Roughly, instead of verifying the signature in the KL, we verify a constraint that guarantees that the signature (or whatever way the user prefers) is verified, or, more precisely, that the user authorised the action.

To generalise, authorisation abstraction = replacing a specific authorisation constraint with another more general constraint that guarantees that the removed constraint is verified elsewhere.

AA examples in shielded kudos

The existing version of the kudos app already have AA:

  • KL-DL authorisation abstraction. Instead of having a single logic governing all possible kudos denominations, we abstract away the denomination logic and bind it to the shared KL. The binding mechanism is based on having the same logic for all kudos (KL), including the DL hash in the label and verifying that the relevant logic is present in the same action
  • Receive authorisation abstraction. The user can specify their own constraints on receiving in the receive logic. The binding is ensured by signature verification in KL.

Abstraction components

Authorisation abstraction involves three components:

  1. Ownership mechanism. Currently we express identity using public keys.
  2. Authorisation constraint carrier. In both existing cases the constraints are carried by resources. In the first case the carrier is a resource of the sub-kind related to the main kind, and in the second case the constraint is carried in a resource of independent kind.
  3. Verification binding mechanism. We need to make sure that the constraints we are abstracting are verified elsewhere, so that they cannot be substituted by other constraints by a malicious actor. In the first case the binding is done using resource fields, in the second case the binding is done via the signature from the user - externally.
Internal binding External binding
Independent kind ? Receive abstraction
Related kind KL-DL abstraction ?

Can we have internal binding for independent kinds?

Independent kinds have different resource logics (otherwise we could express the logics as related). That means we can’t make judgements about the other logic by the fields of the associated resources. The fact that a label/value contains some public key doesn’t imply that this public key is used for anything by this resource.

Can we have external binding for dependent kinds?

In principle, we could, but why, if we can use internal binding, which seems to be always better?

Internal binding External binding
Independent kind :cross_mark: Receive abstraction
Related kind KL-DL abstraction :thinking:

The current state of the signature constraint

Currently the KL contains a signature verification constraint - external binding for the existing receive abstraction. If we want to abstract the signature away, we essentially want to get rid of the external binding currently hardcoded in KL. At the same time, the authorisation mechanism should ideally be independent of the kudos application: the authorisation logic verifies the external authorisation proof (expressed cryptographically for integrity).

Here are some ways we could try:

  • Related kinds + internal binding: in other words, define an authorisation (and possibly the receive logic) kind to be related to the main kudos kind. It would work, but makes not much sense. I don’t like this idea.
  • Independent kinds + external binding: replacing a signature over the receive logic with a signature over the authorisation logic that authorises the receive logic. It creates a chain of authorisation logics, doesn’t solve the problem in principle, but does abstract the receive authorisation away. I don’t like this idea either.
  • As was suggested at the last cryptography meeting, we can try to change the identity form, in particular switch from public key to a pair (public key, receive logic). I’m going to explore this idea in the rest of the post.

Considered solution: change the form of identity

Let’s imagine that an identity is now expressed as (K_{pub}, L_{recv}). Note that the sender needs to know:

  • the value L_{recv} to prove that there is the corresponding resource in the same action
  • the value K_{pub} to pass it as private input to the receive logic (for the first constraint)

Where do we currently use ownership:

  • KL:
    • value encodes the owner of the resource
    • KL create constraint: receive logic verification (the constraint we want to abstract) - signature verification.
  • DL example:
    • kudo label includes the issuer’s identity
    • consume constraint for both ephemeral (issuer’s identity) and persistent (owner’s identity) resources - signature verification.
    • create constraint for ephemeral resources (issuer’s identity) - signature verification.
  • Non-trivial receive logic example:
    • label contains the owner’s identity
    • create constraint (verify the owner of the kudo against the receive logic owner)

Would the scheme work with the new identity form?

  1. We can’t use that form of identity in the receive logic label: we introduce a circular dependency. We can use the public key only, but that kind of breaks the definition of identity. Can be acceptable if everything else works.
  2. The receive logic can’t verify that the kudo is created for the expected user. It can verify the public key, but can’t verify the second component of the new identity L_{recv} - circular dependency.
  3. Everything seems to be fine with the DL example - we strip the second component of the identity and use the public key to verify signatures.
  4. The KL constraint issue doesn’t seem to be solved: since the sender knows the components of the identity, they can replace the second component with a simpler logic - we still need to authorise the receive logic.

To summarise, I don’t see how changing the identity form would solve the problem, but I might be missing something. I’m looking forward to see your thoughts.


  1. modulo possibly integrated update mechanisms that are out of scope of this post ↩︎

Could you elaborate the approach a bit more, and why you don’t like it? What I understand (maybe it’s not what you have in mind) is to trigger a verify authorisation logic, based on what is specified in the kudos label. Something like this: (picture based in the original design, might be outdated)

Because authorisation abstraction mechanism is not specific to the kudos application. In the intended RM design we would write a standalone authorisation abstraction app that any other app, including kudos, could use, without recreating the same thing from scratch. Using related kinds implies that authorisation abstraction mechanism is tied to the parent application (in this case - kudos), which in turn means that every application that uses authorisation abstraction will have to “recreate” the same mechanism. It is kinda like implementing all the libraries you use for coding from scratch every time.

More explicit cons:

  • unnecessary code/logic duplication and application complexity
  • the built-in AA mechanisms cannot be trusted by competing apps. In case we want kudos1 to be compatible with kudos2 (note that kudos1 and kudos2 here are not denominations but different instances of the kudos app. You might wonder why we need them, but it isn’t really up to us if they exist or not, and if they do, we need to make sure they can interoperate. In practice we care more generally about app1 and app2, not kudos1 and kudos2, but specifics work better for the example), the transition rules will be explicit and whoever defines them, have to understand in detail both AA mechanism of kudos1 and kudos2 to make sure nobody can fuck the other party over. Imo it is better when a non-competing app provides a mechanism all competing apps can use. It also makes them all compatible by default.
  • AA fragmentation. Having a single AA mechanism means that the user can possibly compose or combine authorisation for multiple apps. Using dependent mechanism means AA cannot be composed naturally, it has to be done explicitly

It does work well for the kudos application alone, but overall I think it is a bad design decision in the broader context.

If we don’t want to deal with the broader context now, I think it is easier just leave it the way it is. Otherwise we put a lot of effort into something that doesn’t actually give us what we want (we care more about general composability than the perfection of any particular app)

1 Like

OK. I see the benefit of sharing logic across applications. I think we have different meanings of ‘abstraction’ in mind, though. If by it we understand a shared and universal piece of logic intended to work in all scenarios, then I agree with you. Realizing this abstraction is hard; maybe even impossible, given we don’t have the full scope of possible apps; i guess we can only hope for good approximations.
What I had in mind was to switch/implement different ways of authorising receives within kudos’ world. In this second interpretation, the abstraction simply means freedom to choose.

Authorising via triggering resources is nothing but taking (your) kudos’s design to its ultimate consequence, I think: the same way DL logic is triggered, so is VAL logic. But maybe there is some technical stopper that I fail to see, and the sketch of the picture above doesn’t work.

Yeah, we can leave it as it is. Good enough for an MVP to be honest.

1 Like

Could we move the second receive authorization to the receive logic instead of verifying it in KL? The we can further abstract away the current signature verification. While your concern about replacing the second component with simpler logic remains unsolved, however, if the identity is now expressed as (K_pub, L_recv) and the L_recv is replaced, the resource may be sent to the wrong receiver/identity. The receiver could then claim they did not receive it as only partial identity(K_pub) is used. We can not prevent senders from sending resources to invalid or wrong identities. If we only define K_pub as the identity, correct identify/K_pub with an unexpected L_recv could be an issue and we have to explicitly verify receive authorization in KL.

Yes, the circular dependency is annoying. The receive logic at least needs to load two resources: the self resource and the corresponding kudo resource. It can obtain the identity from kudo_value, check if self_logic_ref equals kudo_value.L_recv, and enforce other constraints on K_pub. Additionally, placing kudo_resource_cm in receive_logic_label ensures consistency between the receive logic resource and the kudo resource. Does it make any sense? Could it also address your concern in question 3?

Btw, it might be worth reading the section 4.5 “Identify framework” in ZKP reference. Although we currently only care about the spending and receiving properties

2 Likes

I don’t think it is hard actually, I think it is simple because then we don’t have to think about all the apps, that is the beauty of abstraction.

Authorisation is just some function that the user trusts can only be computed correctly by someone who is authorised. We don’t care what this function is or can be, and that definition of authorisation is not gonna change depending on the application.

All we need to figure out is to switch from the absolute check done in the application logic to a relative check of an authorisation resource. This mechanism is essential to realise full abstraction of any function.

I think that is the same difference as between the prior kudos app design and the current one: the prior version had some options implemented, but it wasn’t extensible. The type of abstraction you describe will likely have a higher resource and constraint overhead (because we have to explicitly specify all the options we provide), but it does require less research. The full abstraction tho requires more research work, and maybe even system design updates, but if we have it, it will be minimal (one check, one resource of arbitrary subkind of a fixed kind, no branching) and infinitely extensible, kinda like denomination logics work now.

There is a difference here because DL and KL are related directly and bound by relative sub-kind constraints associated with the same resource, and authorisation logic is independent (so is receive logic, and that is why we need to authorise it) and it would be semantically wrong to bind either receive or authorisation logic to a kudo.

1 Like

What do you mean by the second receive authorisation? We only have one.

The sender creates the receive logic resource, so I’m not sure we can ensure that it happens.

ah, yes, I mean the second authorization which is the receive authorization.

The KL triggers the receive logic, constrains the receive resource label to equal kudo_resource_cm/tag, and the receive logic checks its label against kudo_resource_tag for mutual referencing between kudo and receive resources. If the triggered receive logic uses a replaced label from the sender, the context (nullifiers and commitments) of the action changes.