Parties and users on a Canton ledger
Identifying parties and users is an important part of building a workable Canton application.- Parties are unique across the entire Canton network. These must be allocated before you can use them to log in, and allocation results in a random-looking (but not actually random) string that identifies the party. Parties are a built-in concept.
- On each participant node, you can create users with human-readable user IDs. Each user can be associated with one or more parties allocated on that participant node, and refers to that party only on that node. Users are a purely local concept, meaning you can never address a user on another node by user ID, and you never work with users in your code; party IDs are always used for these purposes. Users are also a built-in concept.
Parties in Daml SDK
When you allocate a party with a given hint Alice in a Canton ledger you get back a party ID likeAlice::1220f2fe29866fd6a0009ecc8a64ccdc09f1958bd0f801166baaee469d1251b2eb72. The prefix before the double colon corresponds to the hint specified on party allocation. If the hint is not specified, it defaults to party-${randomUUID}. The suffix is the fingerprint of the public key that can authorize topology transactions for this party.
If you are working with a Canton sandbox, the keys are generated randomly. As a consequence the suffix will look different locally and every time you restart Sandbox and you will get a different party ID.
Party ID hints and attributes
A party allocation is rejected if a party with the given hint already exists. The client can safely send the same request with the same hint, which will either allocate a party if the previous request failed or fail itself. Party IDs are not human-readable, and the hints embedded in the prefixes are not universally unique. This makes associating parties with actual entities difficult. To alleviate this problem, we need a field or set of fields that describe a party in greater detail. The Ledger API contains a mechanism that allows associating additional attributes with a party in a dedicated metadata field,localMetadata, in the JSON Ledger API, local_metadata in the gRPC Ledger API.
This metadata is stored locally on the participant hosting the party and is not shared across the network.
Authorization and user management
User management allows you to create users on a participant that are associated with a primary party and a dynamic set of actAs and readAs claims. Crucially, the user ID can be fully controlled when creating a user, unlike party IDs, and is unique on a single participant. You can also use the user ID in Access Tokens. This means your IAM, which can sometimes be limited in configurability, only has to work with fixed user IDs. However, users are purely local to a given participant. You cannot refer to users or parties associated with a given user on another participant via their user ID. You also need admin claims to interact with the user management endpoint for users other than your own. This means that while you can have a user ID in place of the primary party of your own user, you cannot generally replace party IDs with user IDs.Working with parties
So how do you handle the party IDs? The primary rule is to treat them as opaque identifiers. In particular, don’t parse them, don’t make assumptions about their format, and don’t try to turn arbitrary strings into party IDs. The only way to get a new party ID is as a result of a party allocation. Applications should never hardcode specific parties. Instead, either accept them as inputs or read them from the contract or choice arguments.Daml script
In Daml script,allocateParty returns the party ID that has been allocated.
This party can then be used later, for example, in command submissions.
When your script should refer to parties that have been allocated outside of the current script,
accept those parties as arguments and pass them in via --input-file.
Similarly, if your script allocates parties and you want to refer to them outside of the script,
either in a later script or somewhere else, you can store them via --output-file.
You can also query the party management and user management endpoints and get access to parties that way.
Keep in mind, though, this requires admin rights on a participant, and there are no uniqueness guarantees for display names.
That usually makes querying party and user management endpoints only an option for development,
and we recommend passing parties as arguments where possible instead.
Java bindings
When writing an application using the Java bindings, we recommend that you pass party IDs in as configuration, e.g. CLI arguments, JVM system properties, or environment variables, rather than hardcoding them. If your application authenticates with user access tokens, you can avoid handling party IDs directly: look up the authenticated user’s primary party and rights via the User Management Service and act as that party.How to allocate and query parties
Canton Participant Node exposes a party management service that allows creation and discovery of the parties. This guide explains how to programmatically manipulate the parties using the JSON Ledger API, which is described using OpenAPI specifications.Start Canton Participant Node
Ensure that your Canton Participant Node opens a JSON Ledger API HTTP port by adding a flag to the Canton Participant startupHow to query for existing parties
To list all parties known to the participant, issue a GET request towards thev2/parties endpoint.
isLocal attribute is set to true if the participant hosts the party and the party shares the same identity provider as the user issuing the request.
How to create a new local party
To create a new party, issue a POST request towards thev2/parties endpoint.
partyIdHint and the namespace fingerprint of the entity overseeing that party. Typically, it is the fingerprint associated with the Canton Participant Node.
partyIdHint in your request, the Participant Node selects a random hint string.