Party permissions

Hello,

Is it possible to allow only certain parties to do certain things? Let’s say you have a contract like:

template Thing
  with
    admin : Party
    description : Text
  where
    signatory admin 

It is highly likely that in my app we will want to restrict which users can create the Thing contract (‘admins’, in this case).

Is this possible? Would it be something to be specified on the deployment platform (e.g. project:DABL)? If so, how?

Thank you!

3 Likes

In this particular case, the signatory clause does just that: It specifies which Parties can create & archive a contract.

Other forms of access control can be managed with observer in combination with choices having specific controllers.

Check out these tutorials for an in-depth look.

Thanks @Luciano. Yes I understand these concepts. But what is stopping any old party from submitting a create Thing contract request on the Ledger’s API? They would appear as the signatory by virtue of putting themselves in the admin field, which is something we don’t want! Maybe I am mistaken in my logic.

So let’s say you have 3 known parties, only one of them is an admin. We don’t want the other two parties to be able to be in the admin field of the Thing contract.

2 Likes

I see your point. This is actually a pretty interesting question!

The short answer would be to add an ensure clause to check the party matches a pre-specified ‘admin’ party.

You can use this in combination with partyFromText : Text -> Party to check for a known identifier. However, this is pretty hacky and not recommended, because in a prod environment, you may not have control over the identifiers used to create the parties - they should be opaque. To work around this, you would need a ‘meta’ user contract, that obfuscates the Party type. But in this case you’re just trading one problem for another (How do you know which is your ‘admin’ contract?).

I’ll have to think about this some more. Perhaps someone else has got a better idea …

If only Things created by the admin are valid, then you have to know this party by name (regardless if it’s an obfuscated party id or not). So your application (UI, backend code) can simply only consider Things that have the correct admin set. You can’t really stop anyone from creating a single-signatory contract, but your application can know which are the valid ones to consider.

Ah okay. I thought that maybe it may be possible to have the deployment platform specify the users that can act as signatories on specific contracts.

Is it common in blockchain to have users that can do things others can’t? Or is that a ‘bad’ design pattern?

EDIT: Also, is it a thing to query some external DB within the smart contract code? I guess the answer is a resounding no!

1 Like

Definitely a “no” to the DB question. It would be impossible to make that deterministic and verifiable.

DLTs are usually quite symmetric with respect to nodes. The whole point is that you are trying to remove trusted central parties. The same is not true for all applications running on such platforms. Usually application instances are determined exactly by the party (or address on many Blockchains) that is stored on the contracts as the “admin”. That’s the pattern @georg suggests. Just make sure to only query contracts with the correct admin party.

Hardcoding parties using partyFromText is a hack, but one that is common in the Blockchain world where addresses are quite commonly hardcoded. The reason I’d not recommend that in DAML is that you loose application portability not just between platforms, but between ledgers on a given platform. E.g. you wouldn’t be able to move your application from DABL staging to DABL prod without changing the hardcoded party in the package.

1 Like

Cheers. I’ll find a way!

That being said, looking at the docs for Hyperledger Fabric and it seems they have some way of specifying access controls. Maybe that is a different thing to what I am thinking about…

It’s possible (and I think that’s what Fabric does) to restrict user access on a node. So a node could say “I will reject any command submissions that would create a Thing with an admin other than admin.” However, that doesn’t stop another node to create a Thing with a different admin. The node with the restriction may not even know about it.

If the whole ledger is operated by one user, as it is in DABL, it would then be possible to enforce this policy globally. However, such a feature doesn’t exist in DAML/DABL at this point. It would also harm application portability in a serious way. Your application would start relying on a ledger topology where such restrictions can be enforced globally.

1 Like

Definitely a “no” to the DB question. It would be impossible to make that deterministic and verifiable.

This being said, I do recall hearing about smart contract ‘oracles’; external sources of information that play a role in the control flow of the smart contract code execution. Is that not similar to a DB query? I don’t think oracles exist in DAML.

This is a great new question that I’m sure others are interested in as well. Would you mind posting this separately?

1 Like

You must always check the signatories of a contract before you use it.

It’s an important property of the DAML architecture that you can only trust something once you have seen it on the ledger, and that trust is explicitly constrained to the signatories of the associated contract.

What this means is that it is always a bug to fetch a contract without then checking you trust its signatories.

Yes. Anyone can always create any contract at any time provided they are the sole signatory of that contract. So whether you are writing DAML code that just fetched a contract from the ledger, or writing an application that is reading an ACS service. You must always check the signatories of a contract before you use it.

Sorry haven’t been on the forum in a while, will post it now!

Instead of checking that the party as text meets a certain pattern, wouldn’t it be better to hardcode a code in the contract and make it necessary to enter a key when creating that contract so that its hash (calculated with DA.Text.Sha256) is equal to the code hardcoded?

In this way, only the person who wrote the contract would know the correct key.