> For the complete documentation index, see [llms.txt](https://docs.catalyx.solutions/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.catalyx.solutions/catalyx-blockchain-manager/canton-network/version-2.0/validator-management/external-and-multi-host-parties.md).

# External & Multi-Host Parties

{% hint style="info" %}
**Version note.** Single-host external party onboarding shipped in 2.0.0. **Multi-host hosting, the Hosting Proposals sub-tab, and hosting amendments were added after 2.0.0.** If your console shows a two-step onboarding flow with no **Hosting** step, you are on 2.0.0 — upgrade to use the features on this page.
{% endhint %}

## Two ideas, one feature

Canton parties normally have their keys held by the participant that hosts them. Two capabilities change that, and they compose:

<table><thead><tr><th width="230">Capability</th><th>What it gives you</th></tr></thead><tbody><tr><td><strong>External parties</strong></td><td>The party's signing key lives <em>outside</em> the participant — with the party's owner. The participant cannot act on the party's behalf; the owner signs its own transactions.</td></tr><tr><td><strong>Multi-hosting</strong></td><td>A single party is hosted on <em>several</em> participants, which may belong to different organisations. The party survives the loss of any one of them.</td></tr></tbody></table>

### Why multi-host

> A party hosted on a single validator is a single point of failure: lose that participant and the party can no longer act. Canton addresses this with *multi-hosting* — replicating a party across several participants, which may belong to the same operator or to different organisations.

Typical reasons to reach for it:

* **Resilience** — the party keeps working through the loss of a validator, a cluster, or a region.
* **Cross-organisation arrangements** — a party jointly hosted by two institutions, with neither able to act unilaterally.
* **Disaster recovery** — a standby participant in another cluster already holds the party's data and can confirm for it.

***

## The one idea that explains the whole workflow

> **Hosting is consent.** A participant stores a party's data and takes part in confirming its transactions, so no one can be volunteered to host: every named participant authorizes for itself.

This is why onboarding does not "push" a party to other participants. Onboarding allocates the party on **your** validator only. Every other named host sees the request in **its own** Hosting Proposals tab and approves it there.

And it is why there is no export, no bundle, and nothing to send:

> This works because the **synchronizer topology store is shared**. A proposal naming a participant is visible to that participant the moment any host submits it, and the stored transaction already carries the party's signature. There is nothing left to send.

A co-host in your cluster and a co-host in another organisation follow the identical path. There is no privileged local case.

### Two signatures, two different meanings

<table><thead><tr><th width="240">Signature</th><th width="220">Made by</th><th>Means</th></tr></thead><tbody><tr><td>Over the multi-hash</td><td>The party's key holder</td><td>"I want to be hosted on these participants"</td></tr><tr><td>The participant's own</td><td>Each hosting participant</td><td>"I agree to host this party"</td></tr></tbody></table>

A participant's signature is added by *submitting the transaction on that node* — its key material never leaves it. That is what makes hosting genuine consent rather than something the platform could arrange on a participant's behalf.

{% hint style="danger" %}
**The signature is spent on the host set.** The list of hosts is written *inside* the topology transactions that the multi-hash covers. So:

* hosting must be decided **before** the party signs — the wizard's step order is a protocol constraint, not a layout choice;
* a host named in error is **unrecoverable**. Allocation fails, the signature is consumed, and you must restart onboarding with a fresh party hint.

Check every participant UID before you move to the signing step.
{% endhint %}

***

## Permissions and threshold

### Hosting permissions

Canton defines three permissions. CatalyX offers two when onboarding an external party.

<table><thead><tr><th width="180">Permission</th><th width="150">In the console</th><th>The host can</th></tr></thead><tbody><tr><td>Confirmation</td><td><strong>Confirming</strong></td><td>Confirm the party's transactions.</td></tr><tr><td>Observation</td><td><strong>Observing</strong></td><td>Observe the party's transactions. It cannot confirm.</td></tr><tr><td>Submission</td><td><em>not offered</em></td><td>Submit transactions on the party's behalf.</td></tr></tbody></table>

{% hint style="info" %}
**Submission is deliberately unavailable for external parties.** An external party signs its own transactions, so no participant submits on its behalf. This is a Canton topology constraint, not a CatalyX restriction.
{% endhint %}

Note also that the effective permission is the **lower** of what the synchronizer grants a participant and what the party mapping grants it. A host you name as confirming will behave as observing if the synchronizer restricts that participant.

### The confirmation threshold

This field is misread more often than any other in the feature, so it is worth stating twice.

> Authorization is **all-of-N**: every named host must sign. The separate `threshold` field is *not* a signing threshold — it governs how many confirming hosts must confirm each future ledger transaction once the party is live.

<table><thead><tr><th width="290">The threshold does</th><th>The threshold does not</th></tr></thead><tbody><tr><td>Set how many confirming hosts must confirm each of the party's ledger transactions, once it is live.</td><td>Control how many participants must authorize the hosting itself. That is always <strong>all</strong> of them.</td></tr><tr><td>Count only hosts that can confirm.</td><td>Count observation-only hosts.</td></tr><tr><td>Get ignored entirely when every host is observation-only.</td><td>Affect whether the party becomes usable.</td></tr></tbody></table>

Rules the console enforces:

* At least one confirming participant is required.
* The threshold must be at least 1, and no greater than the number of confirming participants.
* Your own validator counts as a confirming participant unless you tick **This validator observes only**.

***

## Onboarding an external party

Start from **Parties → Onboard External Party** on the validator.

{% stepper %}
{% step %}
**Identity — the party's key**

*Provide the party's public key. The participant will generate topology transactions for you to sign.*

<div data-with-frame="true"><figure><img src="/files/XjmD7YCLGDq8DJVSauSJ" alt=""><figcaption></figcaption></figure></div>

| Field                       | Notes                                                                                                     |
| --------------------------- | --------------------------------------------------------------------------------------------------------- |
| **Party hint**              | 2–64 characters, letters, digits, hyphens, and underscores only. Incorporated into the generated party ID |
| **Key algorithm**           | **Ed25519 (recommended)** or **ECDSA P-256**                                                              |
| **Public key (DER Base64)** | X.509 SubjectPublicKeyInfo, DER encoded, then Base64                                                      |

The wizard shows the commands to produce a key pair:

```bash
openssl genpkey -algorithm ed25519 -out key.pem
openssl pkey -in key.pem -pubout -outform DER | base64 -w 0
```

Nothing is sent to the participant at this step. Click **Next: Hosting →**.

{% hint style="warning" %}
`key.pem` is the party's private key. Whoever holds it controls the party. Generate it on the party owner's own machine wherever possible, and store it in a secrets manager or hardware token — not alongside your platform configuration.
{% endhint %}
{% endstep %}

{% step %}
**Hosting — choose the host set**

*Choose which participants host this party. This cannot be changed later — the host set is covered by the signature.*

<div data-with-frame="true"><figure><img src="/files/nGua9t06FNBIhAKpyRYZ" alt=""><figcaption></figcaption></figure></div>

Leave this step untouched to host the party on your validator alone. Otherwise:

* **Add participant** adds a row. Enter the participant UID in `alias::fingerprint` form, and choose **Confirming** or **Observing**.
* Tick **This validator observes only (does not confirm)** if confirmation should rest entirely on the other hosts.
* Set the **Confirmation threshold**. The hint below it tells you how many confirming participants you currently have.

Participant UIDs are entered as free text rather than chosen from a list — a production synchronizer carries hundreds of participants, and the useful ones are usually on other clusters. A participant UID is a public identifier; naming one needs no credentials for that node.

**The advisory lookup.** When you leave a UID field, CatalyX checks it against the synchronizer and reports:

| Chip                                                                                               | Meaning                        |
| -------------------------------------------------------------------------------------------------- | ------------------------------ |
| *Checking synchronizer…*                                                                           | Lookup in flight               |
| *Known on this synchronizer*                                                                       | The participant exists         |
| *This is this validator — remove it, it is already a host*                                         | You named your own participant |
| *Not found on this synchronizer… You can continue, but allocation will fail unless it joins first* | No match                       |

{% hint style="warning" %}
**The lookup warns; it never blocks.** Naming a participant that has not yet joined the synchronizer is legitimate — but the party's signature is spent at the next step, so a genuine typo costs you the whole onboarding. Resolve every warning before continuing.

All hosts must be on the **same synchronizer**. A participant that is absent from your local topology store — including one whose validator has been offline long enough to fall behind — will not resolve, and allocation will fail.
{% endhint %}

Click **Generate Transactions →**.
{% endstep %}

{% step %}
**Sign the multi-hash**

*Sign the hash below with your private key and paste the Base64 signature.*

The participant has generated the party ID and a **multi-hash** covering the topology transactions. When you named co-hosts, a **Co-hosts** line reports how many additional participants must authorize.

Give the multi-hash to the party's key holder to sign. The wizard shows the command for the chosen algorithm:

```bash
echo "<multi-hash>" | base64 --decode > hash.bin
openssl pkeyutl -sign -inkey key.pem -rawin -in hash.bin | base64
```

Paste the Base64 signature into **Signature (Base64)** and click **Complete Onboarding**.

{% hint style="danger" %}
This is the point of no return for the host set. If allocation fails because a named participant does not exist, the signature is consumed — you cannot retry with a corrected host list. Start again with a **fresh party hint**.
{% endhint %}
{% endstep %}

{% step %}
**Distribute — wait for the co-hosts**

Single-hosted, the wizard reports **External Party Onboarded** — *Hosted on this validator alone. The party is ready to use.*

Multi-hosted, it reports **Awaiting Other Hosts** and lists each participant still owing approval:

> The party is **not usable yet**. Each participant above must approve hosting it. The request is already visible to them — it appears under Hosting Proposals on their own Parties tab, whether they are in this cluster or another one. Nothing needs to be sent to them.

Click **Done**.
{% endstep %}
{% endstepper %}

***

## Approving a hosting proposal

This is the other half of the workflow, performed by each co-host's operator.

{% stepper %}
{% step %}
**Open Parties → Hosting Proposals**

The proposal is already there. Nothing was sent to you and there is nothing to import — the synchronizer's topology store is shared, and the proposal already carries the party's signature.
{% endstep %}

{% step %}
**Check what you are agreeing to**

The row shows the party ID, every named host with your own participant tagged **this participant**, and the confirmation threshold.

{% hint style="warning" %}
Approving means this participant will store that party's data and take part in confirming its transactions. Only approve proposals you recognise.
{% endhint %}
{% endstep %}

{% step %}
**Click Approve**

There is no confirmation dialog. A toast reports either *Hosting approved — the party is now active* or *Hosting approved — still waiting on other hosts*.

Rows where this participant has already authorized show *Waiting on other hosts* instead of a button.
{% endstep %}
{% endstepper %}

{% hint style="info" %}
**Approval is safe to repeat.** Re-submitting an identical approval succeeds rather than erroring, so retrying after a network failure is harmless.

**A participant is only asked to approve when it takes on more responsibility** — when it is being added as a host, or when its permission is being strengthened. If you are named in a proposal but see no **Approve** button, nothing is required of you.
{% endhint %}

***

## Changing a party's hosting

{% hint style="info" %}
**Version note.** Hosting amendments were added after 2.0.0 and are newer than the onboarding flow above. Exercise them in a non-production environment first.
{% endhint %}

Hosting on an existing party can be changed: add a host, remove one, change a permission, or change the threshold. All four are the same operation — the party's hosting mapping is replaced at the next serial.

Open **Parties → Hosted Parties**, expand the party, and click **Edit hosting**.

<div data-with-frame="true"><figure><img src="/files/EEgvyRyMN4kUHZqrmqgz" alt=""><figcaption></figcaption></figure></div>

{% stepper %}
{% step %}
**Edit Hosting**

*Replace the full set of participants hosting this party. Anything removed here stops hosting it.*

The current host set and threshold are pre-filled. Edit them, then click **Prepare Change →**.

{% hint style="danger" %}
**This is a replacement, not a delta.** What you leave in the list becomes the party's complete new host set — anything you remove stops hosting the party. At least one host must remain.
{% endhint %}
{% endstep %}

{% step %}
**Sign the Change**

*Sign the transaction hash with the party's private key and paste the Base64 signature.*

The modal shows the serial transition — `current → next` — and a transaction hash to sign, with the matching `openssl` command. Paste the signature and click **Submit Change**.

{% hint style="warning" %}
Check the **Key algorithm** selector matches the party's actual key. It defaults to Ed25519 and does not detect the party's algorithm, so an ECDSA P-256 party needs the selector changed or the signature will be rejected.
{% endhint %}
{% endstep %}

{% step %}
**Wait for approvals**

A toast confirms *Hosting change submitted at serial `n` — awaiting approval from affected participants*.

As with onboarding, every participant taking on more responsibility must approve from its own **Hosting Proposals** tab before the change takes effect.
{% endstep %}
{% endstepper %}

### Not supported

{% hint style="warning" %}
**Multi-hosting a participant-managed party.** A party allocated with **Allocate Party** is managed by the participant, which holds its keys. There is no external key holder to sign a hosting change, so its hosting cannot be amended through this flow — which is why **Edit hosting** only appears for externally-signed parties.

If you need a party hosted on more than one participant, onboard it as an external party from the start.
{% endhint %}

***

## Things to know

Behaviour established by testing against a live network:

<table><thead><tr><th width="330">Question</th><th>Answer</th></tr></thead><tbody><tr><td>Does generating the topology validate that a named participant exists?</td><td><strong>No.</strong> It succeeds for an unknown UID; allocation then fails — <em>after</em> the party has signed.</td></tr><tr><td>Is a multi-hosted mapping effective before all hosts authorize?</td><td><strong>No.</strong> It exists as a proposal and is absent from effective state. The party is unusable until the last host approves.</td></tr><tr><td>Is approval idempotent?</td><td><strong>Yes.</strong> Replaying an identical approval succeeds. Re-approving is safe.</td></tr><tr><td>Can the onboarding flow amend an existing party?</td><td><strong>No.</strong> It always creates a party at the first serial. Use <strong>Edit hosting</strong> instead.</td></tr><tr><td>Is a proposal visible to participants that did not submit it?</td><td><strong>Yes.</strong> The synchronizer's topology store is fully shared — a single query returns hundreds of proposals, nearly all naming participants the querying node has no relationship with.</td></tr><tr><td>Do stored proposals carry the party's signature?</td><td><strong>Yes.</strong> Which is why nothing has to be transferred between operators.</td></tr></tbody></table>

Additional notes:

* **Topology propagation is not instant.** Immediately after an approval, a party may still read as pending. The console polls for up to 30 seconds; if in doubt, refresh the Hosted Parties list.
* **A blank permission in the advisory lookup is normal.** Per-participant synchronizer terms are optional in Canton; whether the participant is *on* the synchronizer is the signal that matters.
* **Naming your own validator as a co-host is not blocked.** The lookup warns you, but nothing prevents it — remove the row.

## Related

* [Parties tab](/catalyx-blockchain-manager/canton-network/version-2.0/console-guide-canton/validators/parties.md) — the console screens in detail
* [Wallet Gateway](/catalyx-blockchain-manager/canton-network/version-2.0/validator-management/wallet-gateway.md) — delegating party signing to an external custody provider


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.catalyx.solutions/catalyx-blockchain-manager/canton-network/version-2.0/validator-management/external-and-multi-host-parties.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
