I need help in understanding the role of "maintainer"

G-d willing

Hello,
I am trying to figure up what is the purpose of defining the maintainer in a template.
In correlation to a database, the definition of the “key” is actually the list of the fields in a table that create the uniqueness of a row and prevents data duplications.
So, how the “maintainer” helps in this correlation? I understood that it is somehow related due to the reason that on distributed ledgers no one can guarantee the uniqueness of the data.

For example, let’s say I create a template that holds employees’ data as follows:
template Employee
with
user: Party
employeeNumber: Int
where
signatory user
key user, employeeNumber
maintainer key._1

how is it going to be different if I add the emloyeeNumber to the maintainer section, or, how it will be different if the maintainer will be set to key._2 instead, or both of them will be in the set?

Can you please explain that in correlation to the database world, I think it will be easier for me to understand it tat way.

Thanks,

I would start with the documentation on key maintainers.

With respect to a database analogy, hmm, let me give it a try:

Suppose that you had a table where DB user Alpha could see and update half of the rows, and a different DB user Bravo could see and update the other half of the rows. You wish to perfectly separate their interactions, so it is not possible for Alpha’s database interactions to interfere with, or even observe, Bravo’s interactions, and vice versa.

In this case, you cannot create a unique constraint on a column such as id. That is because if Bravo creates a row with id=42, then Alpha can observe the creation of that row merely by attempting to create its own id=42 row.

You can solve this problem by

  1. requiring row ownership to be embedded within the table. So you must create a column maintainer, and moreover, DB user Alpha may only set the value of this column to Alpha, and likewise for Bravo.
  2. requiring the maintainer column to be in every unique constraint. So instead you must set (maintainer, id) to be the unique constraint, which means that Alpha can only create the key (Alpha, 42), and Bravo can only create the key (Bravo, 42), and there is no possible way for their unique keys to interfere with or observe each other.

As the documentation states, there’s no need for the maintainers to “do” or “maintain” anything; their mere presence in the unique constraint is enough to “maintain the constraint’s integrity” without leakage.

2 Likes

Hi @Stephen, first I would like to thank you for attempting to help and answer my question.

Trust me, I have read it before posting this question.

But, I guess I am missing something in here.
Let’s say that except for the “user: Party” field, I will have a social security number field. This field is unique and cannot be duplicated in the system. So why can’t I use the social security number field as the maintainer? Why do I need to have the “user” field as a maintainer? I don’t understand how the maintainer helps in keeping the uniqueness in the table.

In other words, I don’t understand why I need to “maintain” the key in the first place? Why defining the keys alone is not enough? It shouldn’t have anything to do with the ability to view data of someone else, as this is done by the definition of the signatory and the observer. So following the example you mentioned about Alpha & Bravo, I know that the Alpha’s DB rows won’t be visible to Bravo since he is not the observer of the specific template.

I’m not sure that the “database” analogy is entirely suitable. As much as we try to provide a clean interface to the underlying ledger as an event source, for you to better understand maintainers you should probably rather think of a network of interconnected databases, separated by network boundaries and governed by privacy restrictions. This is not a necessary concept for keys as they were implemented up to Daml 1.x, but maintainers were always there with the idea of making this step as we move on closer to the original vision of Daml with the 2.x release, which ships with Canton.

Maintainers are a mechanism to enforce partial uniqueness in a network where not all parties have visibility over the entirety of the information. You need to pin down some kind of ownership of a key to allow for the overall system to be able to provide bounded uniqueness (within the context of a single domain, in the case of Canton). You can learn more about this here.

In summary, while maintainers are not strictly necessary from a “single database” point of view, where information is centralized and controlled by a single operator, they are fundamental to provide the concept of contract keys in a decentralized environment (albeit with a few caveats that need to be put in place for the concept to still work).

Hope this helps.

2 Likes

It’s all about consensus and validation. Imagine I submitted the transaction

create Employee with
  user = bernhard
  employeeNumber = 1
  ...

I’m the only party that gets to see this transaction as you have no observers or other signatories on that contract.

Now imagine you submit

create Employee with
  user = cohen
  employeeNumber = 1
  ...

You are the only party that gets to see that transaction.

So there is no chance to detect, let alone verify or get consensus on the fact that we have both used the same employeeNumber. These two contracts do not exist within the same view of the ledger anywhere. This demonstrates why just setting the key to be employeeNumber doesn’t work. To make uniqueness work, we need to make sure that any two contracts that could clash on key are guaranteed to be visible in one place where the collision can be detected, and that that place has the responsibility to verify collisions.

The maintainer clause defines that place as a set of parties. Since the maintainers are part of the key, any two contracts that could clash have the same maintainers, which means they are both visible to that set of parties. And those parties have the responsibility to verify that any key lookups or collision detection was done correctly.

So I’d implement

template Employee
  with
    employer : Party
    employee: Party
    employeeNumber: Int
  where
    signatory employee, employer
    key (employer, employeeNumber) : (Party, Int)
    maintainer key._1

Now the employer is the one responsible for ensuring uniqueness of the employeeNumber between employees at that employer. But two employees at two different employers can have the same employeeNumber - just as would be the case if the two employers ran completely separate computer systems.

2 Likes

Thank you @bernhard and @stefanobaghino-da for your explanations. However, I still don’t fully get it.

Following @bernhard example, shouldn’t the combination of “employer” and “employeeNumber” creates uniqueness? What does the maintainer do in this regards.

Or, let me even define a more possible scenario which I hope will illustrate my confusion I have here.
You, @bernhard are the employer and I am the employee. Technically you can be the employer for 2 different companies at the same time. and I am working for these 2 companies. Technically, I can have the same employee number in both companies. So how does the maintainer help in here? If that will happen, the uniqueness will be violated regardless of the maintainer.
So, the way I am used to think of uniqueness is that as long as I make sure to define a key with a combination of fields that create uniqueness, that should be suffice. without anyone “owns” the key.

I would like to thank you again for the efforts you are putting in order to explain it for me.

Your example here is actually pretty good because it allows to explain the role of the maintainer:

There are two possible approaches:

  1. the employer is a plain string: how can you ensure the uniqueness of the (employer, employee_number) pair? What prevents anyone from just adding their own contract keyed in the same way? This contract could be not be visible by the same parties because of privacy. You have no way of establishing uniqueness aside from delegating this to a central authority that sees “everything”.
  2. the employer is a signatory of the contract and is defined as the maintainer of the key – in this way, uniqueness is guaranteed by the system as the maintainer will always have visibility over the contract this key is bound to.

Does this make sense?

1 Like

G-d willing

Thanks @stefanobaghino-da for your response, but still I am not getting it.
I will leave it for now as is. Hopefully, I will understand it later on. I guess the fact I am coming from a world of centralized databases for many years is causing me not to fully understand it.

Let’s take a closer look at your employeeNumber example. What does “unique” mean?

First, let’s assume you have two companies, each with one (distinct) employee. Is there any reason they couldn’t both say this is employee #1? I’d say no. In that sense, employeeNumber on its own is not unique. From a “global” perspective, there is no uniqueness requirement.

Now, if you have two employees in the same company, you do want them to have different numbers. So from the perspective of a given company, employeeNumber must be unique.

Say you’re a part-time worker. You work for two companies. Is it a problem if you get issued the same number in both? Would you report it? As the employee, you know of both companies. From the perspective of the employee, employeeNumber does not need to be unique.

So here’s one way to think of the maintainer: it’s the perspective from which the key must be unique.

Now let’s assume we have four companies (A, B, C, D) making joint ventures. The contract looks something like:

template JointVenture
  with
    investors: [Party]
    ventureId: Text
  where
    signatory investors
    key (investors, ventureId): ([Party], Text)
    maintainer key._1

In case you’re not familiar with the notation here, this means we can have any number of parties signing this contract and they’re all both signatories and maintainers.

Now, if A and B do a joint venture and call it “monkey” and then C and D separately make a joint venture and also want to call it “monkey”, should they be allowed to? Arguably yes, because there is no way for C or D to be aware of the deal between A and B. So, again, there is no global uniqueness.

If A and B make a deal and call it “yellow”, then B and C make a deal and want to call it “yellow” too, should this be allowed? Again, yes, because there’s no reason to force B to tell C they already have a separate deal with the same name.

But if A and B now want to make a third deal, it makes sense that they should call it something other than either “monkey” or “yellow”, as that would be confusing.

So, now, we can refine this idea of maintainer a little bit more: the set of maintainers (which must be parties) is the context in which the key is unique.

This is already necessary in a non-distributed context in order to maintain privacy. But it is indeed much more important in a distributed context: who would you ask to in order to check global uniqueness? You wouldn’t necessarily know everyone. So having a set of “responsible parties” as part of the key means when you have a key you know who to ask for the corresponding contract: the maintainers.

If you want a correlation with the database world, just imagine there is a separate table for each set of maintainers, and the unicity constraint is applied on that table.

3 Likes

Thank you very much @Gary_Verhaegen. The way you put it, made me understand that. I am sure I have more to learn about maintainers, but finally, I understand why we need it in the first place.