Manage Participants

Manual vs Automatic Identity Initialization

Similarly to a domain, a participant node can either be initialized automatically, the default behaviour, or manually. Managing the initialization manually is particularly useful when a participant:

  1. Does not control its own identity;
  2. When you do not want to store its identity key on the node for security reasons;
  3. When you want to set a participant’s keys by yourself.

If you want to disable the automatic initialization of a participant node you have to set:

participant.init.auto-init = false

Keys Initialization

Besides a namespace key and a signing key a participant node also has an asymmetric encryption key that it uses to decrypt encrypted transactions. Key are created automatically, however, if you are manually setting up your participant node you must use the following commands to generate your signing keys (for namespace and signing) and the encryption key:

/* Create or register three keys:
 * 1. a signing key that is going to control our identity;
 * 2. a signing key;
 * 3. an encryption key to encrypt transactions;
 */
val ((identityKey, signingKey), encryptionKey) = if (useKms) {
  // user-manual-entry-begin: ManualRegisterKmsKeys
  participant.keys.secret
    .register_kms_signing_key(namespaceKmsKeyId, name = participant.name + "-namespace") ->
    participant.keys.secret
      .register_kms_signing_key(signingKmsKeyId, name = participant.name + "-signing") ->
    participant.keys.secret
      .register_kms_encryption_key(encryptionKmsKeyId, name = participant.name + "-encryption")
  // user-manual-entry-end: ManualRegisterKmsKeys
} else {
  participant.keys.secret.generate_signing_key(name = participant.name + "-namespace") ->
    participant.keys.secret.generate_signing_key(name = participant.name + "-signing") ->
    participant.keys.secret.generate_encryption_key(name = participant.name + "-encryption")
}

If you are using a Key Management Service (KMS) to handle Canton’s keys and you want to use a set of pre-generated keys you must use instead the commands register_kms_signing_key() and register_kms_encryption_key()

Please refer to External Key Storage with a Key Management Service (KMS) for more details.

Participant Manual Initialization

The following steps describe how to manually initialize a participant node after the keys have been generated:

// use the fingerprint of this key for our identity
val namespace = identityKey.fingerprint

// create the root certificate (self-signed)
participant.topology.namespace_delegations.authorize(
  ops = TopologyChangeOp.Add,
  namespace = namespace,
  authorizedKey = namespace,
  isRootDelegation = true,
)

// initialise the id: this needs to happen AFTER we created the namespace delegation
// (on participants; for the domain, it's the other way around ... sorry for that)
// if we initialize the identity before we added the root certificate, then the system will
// complain about not being able to vet the admin workflow packages automatically.
// that would not be tragic, but would require a manual vetting step.
// in production, use a "random" identifier. for testing and development, use something
// helpful so you don't have to grep for hashes in your log files.
participant.topology.init_id(
  identifier = Identifier.tryCreate("manualInit"),
  fingerprint = namespace,
)

// assign new keys to this participant
Seq(encryptionKey, signingKey).foreach { key =>
  participant.topology.owner_to_key_mappings.authorize(
    ops = TopologyChangeOp.Add,
    keyOwner = participant.id,
    key = key.fingerprint,
    purpose = key.purpose,
  )
}