PartyIDs Composition, Storage & Discovery using Namespaces and PartyInfo contracts

  1. The client application layer often needs to get hold of Party IDs in order to submit them to the Daml API as part of template parameters for Create Commands or choice parameters for Exercise Commands. To do this, we are thinking of storing participant node namespaces on a contract on ledger:
template ParticipantNodeInfo
   with
      pn1: Text -- <PN1 namespace>
      pn2: Text -- <PN2 namespace>
      pn3: Text -- <PN3 namespace>
...
  • We have parties with the same hint across the participant nodes, eg, Alice::pn1 and Alice::pn2. So this approach will allow us to dynamically compose partyIds by combining the partyId hint, say, Alice, with the PN namespace from the above contract, giving us the full partyID. Any concerns with the above approach, specifically, storing participant node info on ledger, and updating it by exercising a choice on it every time the ledger topology changes or the ledger is restarted and hence namespaces change?

  1. Is there a way to get hold of a participant node’s namespace via the API? This will eliminate the need to store it on ledger as a contract, simplifying things.

  2. I also need to know in my Java app layer who the observers of a contract are to be. Say I have a contract:

template Asset
    with 
        assetObservers: [Party]
        ...
   where
        ...
        observer assetObservers
  • Let’s say I need to pass in [A,B,C] as the 3 parties at runtime into assetObservers in my Create Command for all contracts I create in my dar (different observers for a different dar), how does my Java app know which parties I need to pass in? It needs to store the info that [A,B,C] are to be the observers for this contract. Is it recommended to store this info on a contract on-ledger, on say a PartyInfo contract that stores the partyIds of all parties, as well as store in it which parties are to be the observers for the templates in my dar?
  1. Is there a better way of doing this? Should we simply pass in the parties on Java app startup as arguments, or maybe store the party info as config on the Java app side?

Hello! Could anyone opine re best practices on these please?

Participant node namespaces are an off-ledger concept. As such, putting this on ledger doesn’t sound to me like a good idea.

Makes sense. Although I would regard a party ID as some form of credential that needs to be known. If you were to use a relational database you would need to have a username to access it and enjoy certain rights, but you wouldn’t store your own credentials on the database you need to access itself.

Please note that respecting party ID hints is currently a behavior of the API (which is mostly useful for debugging) but not a guarantee. The best way to think about party IDs in general is as opaque strings tied to some on-ledger rights and obligations. The right way to bind those to a well-known off-ledger identity is via the user management service.

Not that I know of. Also consider that a party namespace is not necessarily tied to a specific participant, as parties have the option to migrate across participants with their party ID left intact. What you can do as a user is ask for the parties on behalf of which you can act and/or read as.

Manage the party ID as you would manage a set of credentials that need to be known at runtime by the application. Possibly leverage the user management service to know more information at runtime if needed.

I think this goes towards the right direction.

Thanks @stefanobaghino-da

Re the above, my understanding was you are guaranteed to get either a party with ID = hint::namespace or an error, based on what @cocreature mentioned in his/her/their response to Canton PartyId Hint Guarantees.

Could you also comment on the recommended approach for item #3 below please?

This is indeed the current implementation behavior, not an API-level guarantee (cmp. Ledger API Reference — Daml SDK 2.7.6 documentation – the party ID hint can be ignored by the server implementation). We might want to have the actual guarantee in place at some point, but regardless I would still recommend to reason about party IDs as opaque handles regardless of the server behavior.

It’s difficult to understand the problem there. I can’t tell based on what you decide which are the observers. If the observers are “all parties the token holder can read on behalf of” I would probably use the user management service to read this information. If it’s based on some other kind of off-ledger logic, I would use and off-ledger store. If it’s based on some on-ledger workflow, I would keep it on ledger and read it as part of a transaction.