Why can't authorization errors be handled?

In a different thread, @cocreature stated

That doesn’t actually allow you to catch authorization errors though which was part of the original question.

That got me thinking why not?!

3 Likes

Pro tip: if you put your answer to your own question as a second message, you can actually mark it as the answer and then the question looks like it’s answered.

2 Likes

I’m going to answer my own question here, because I’ve been pondering this for the last half hour.

First, I figured you can already write a model isomorphic to any other model in which authorization errors are handleable. First, just make every choice a public choice with a field controllers : Set Party and an initial assert (controllers == expectedControllers). So instead of

controller expectedControllers can
  Foo : Bar
    with 
      ...
    do

write

choice Foo : Bar
  with
    controllers : Set Party
    ...
  controller controllers
  do
    assert (controllers == expectedControllers)
    ...

Secondly, wrap every create in the function

catchableCreate c = do assert (signatory c `subset` (signatory this `union` controllers)) create c

Now every authorization check has become an assertion, which the new exception handling feature can catch.

But then I was reminded why authorization errors are not catchable. Imagine there was a contract c on the ledger at some point with Alice as a signatory. Eve learned of this contract somehow and wants to know whether it’s still active, even through by the Daml privacy model she has no right to get that information. Let’s suppose she could submit this transaction:

try do
  fetch c
catch
  AuthorizationError m -> return ()

One of two things can happen:

  1. Eve gets a contention error saying c does not exist.
  2. Eve gets back a confirmation of a committed transaction including an aborted Fetch.

Whether she gets 1 or 2 must not depend on the activeness of c, otherwise we have an information leak. But 1 has to be possible since the contract may be genuinely unknown to the validators - Alice in this case. So we always have to go with 1 and therefore the authorization error cannot be handled.

So given I said you can build an isomorphic model where we can catch authorization errors, did we introduce a privacy leak with Daml Exceptions? :grimacing:

I believe not. Can you spot where I want wrong with my “isomorphic model”?

By changing a choice to a public choice with an assertion to check controllers, I have decoupled the authorization for the activeness check from the authorization for the execution of the exercise body. Anyone is now authorized to check activeness by calling the public choice. The two models are not isomorphic after all.

Imagine this choice:

choice CheckActive : ()
  with
    fetcher : Party
  controller fetcher
  do
    abort "Abort! Abort!"

This is saying anyone can call this choice and as part of that check the activeness of the surrounding contract. But no exercise of the choice will ever succeed.

Anyone can now legitimately check the activeness of c using

try do
  exercise c CheckActive
catch
  GeneralError m -> return ()

This is one of many subtleties in Exception handling we had to explore in-depth as part of the design of this feature, and I hope to cover this and more in a blog post soon.

What do you think, does the above argument hold up? Do you think authorization errors could be handled without privacy leaks? Let me know :slight_smile:

3 Likes

While I’m certain @bernhard is aware of that I do want to point out for others that this only applies to catching authorization failures within a transaction. @Brian_Weir’s request of catching this on a call to submit is perfectly reasonable and there is nothing fundamental that prevents this.

3 Likes