Skip to content

Add a member to a Decentralized Party

This guide adds a participant to a Decentralized Party that already exists. The new participant becomes a namespace owner and a host of the party. Decentralization Manager then copies the party’s contracts to it.

The API calls this run the add-party workflow. The web interface calls it Add Member.

  • Coordinator: the node of a current host that starts the run.
  • Hosts: the participants that host the party and own its namespace today.
  • New member: the participant that joins.

Every host and the new member take part in the run. Each of them accepts an invitation on its own node.

For a party that is not a Decentralized Party, use another guide:

Membership and governance changes explains how this run fits with governance membership and thresholds.

Check every item. Decentralization Manager refuses the run, or the run fails partway, when one is missing.

  1. The new member runs Decentralization Manager. It connects to its own participant. All nodes of a Decentralized Party must run the same release. The code itself accepts any peer that has the same wire version and reports version 0.1.9 or later.
  2. The nodes know each other as peers. The coordinator and the new member must list each other. Every host must list the coordinator. Set up the full mesh anyway, because a later run can have a different coordinator. See Connect peers.
  3. The new member has every DAR that the party uses. The coordinator checks this before it writes any topology. See Check the new member’s DARs.
  4. The coordinator can read the party’s contracts. The DAR check reads them over the Ledger API, with the party credentials on the coordinator. Open the party page and confirm that Test Auth succeeds.
  5. No other run is in flight for this party. A node refuses to start a kick, add-party, change-threshold, or contracts run for a party that already has a run in progress on that node. The node counts its runs in either role, as coordinator or as peer. The guard is local to each node. Decentralization Manager does not stop two different nodes from coordinating conflicting runs on the same party.
  6. You can take the new member offline for a while. Its participant leaves the synchronizer during the run. See Downtime.

If the new member hosted the party before, read Re-adding a former member first.

  1. Open the party page and click Check DARs. The Packages page opens and compares the party’s hosts.
  2. Add the new member in the Participants box. It is not a host yet, so Decentralization Manager does not add it for you.
  3. Turn on Differences only. A red cell with an error icon marks a package that the new member lacks.
  4. Click the send icon in that cell to distribute the DAR. The new member’s operator accepts it under Approvals. The send icon shows only in a web interface build with admin access.

Package and contract operations describes the DAR workflow and its API.

The new member’s participant disconnects from the synchronizer when it signs the proposals. It reconnects after the contract import ends. While it is disconnected, every party on that participant pauses, not only this party.

The current hosts are not affected. The party keeps transacting on them for the whole run.

Two things set the time offline:

  • How fast the current hosts sign.
  • How many contracts the party holds.

So brief the operators of the current hosts before you start, so that they accept quickly.

The threshold is how many namespace owners must sign a topology change for the party. Decentralization Manager also uses it as the party’s confirmation threshold.

The new threshold must be between 1 and the current number of namespace owners. The new member does not count yet, because it cannot sign until its import completes. The dialog suggests half the owners after the add, rounded up.

The dialog accepts one value above the current number of owners. The node rejects that value with “new_threshold must be between 1 and N”.

To count the new member, run Change Threshold after this run completes. See the Change a threshold section of Membership and governance changes.

On the coordinator:

  1. Open Parties and click the party.
  2. In the Participants section, click the Add member icon.
  3. In Participant to Add, pick the new member. The list holds the peers that do not host the party yet.
  4. Set New Threshold.
  5. Click Add Member.

The coordinator sends an invitation to every host and to the new member.

On every invited node:

  1. Open Approvals. The invitation is under Needs your action.
  2. Click Review ▾. Check the Dec party, the participant under Adding, and the Threshold.
  3. Click Accept.

The run starts when every invited node has accepted. The coordinator shows the run as a card under Approvals, with one dot for each step. During the copy, the card shows a meter: “Sending ACS” on the coordinator, and “Importing ACS” on the new member.

The operator API needs an access token from your identity provider. The caller needs the admin role when the node sets DECPM_ADMIN_ROLE. See Authentication and operator roles.

Start the run on the coordinator. Set NEW_THRESHOLD and OLD_THRESHOLD first:

Terminal window
curl -sS -X POST "$COORDINATOR/add-party" \
-H "Authorization: Bearer $TOKEN" \
-H 'Content-Type: application/json' \
-d '{
"decentralized_party_id": "joint-custody::1220...",
"new_participant_id": "custodian-d::1220...",
"new_threshold": '"$NEW_THRESHOLD"',
"previous_threshold": '"$OLD_THRESHOLD"'
}'

previous_threshold is for display only. The answer is HTTP 202 with the run’s instance_name.

Accept the invitation on every invited node:

Terminal window
ID=$(curl -sS "$NODE/invitations" -H "Authorization: Bearer $TOKEN" \
| jq -r '.invitations[] | select(.invitation_type == "AddParty") | .id')
curl -sS -X POST "$NODE/invitations/accept" \
-H "Authorization: Bearer $TOKEN" \
-H 'Content-Type: application/json' \
-d "{\"id\": \"$ID\"}"

Follow the run on the coordinator:

Terminal window
curl -sS "$COORDINATOR/workflows" -H "Authorization: Bearer $TOKEN" \
| jq '.runs[] | select(.instance_name | contains("-add-party-"))
| {instance_name, status, current_step, step_index, step_total, error}'
# Step Who acts What happens
1 WaitingForPeers Coordinator Waits until every invited node has accepted and connected
2 GenerateNewMemberKeys New member Creates its namespace key and its Daml signing key in its participant
3 ExportState Coordinator Reads the party’s topology, checks the threshold, and checks the new member’s packages
4 CreateProposals Coordinator Builds the new namespace and hosting mappings. The new member gets Canton’s onboarding marker
5 SignProposals All Every node signs. The new member then disconnects from the synchronizer
6 SubmitProposals Coordinator Submits the mappings and opens the export of the party’s contracts
7 SyncAcs New member Imports the contracts block by block, then reconnects
8–12 Clear the onboarding marker All The new member proposes to clear the marker, every node signs, and the coordinator submits
13 RetireLegacyKeys All Removes the party’s old key mapping, if it has one
14 Complete All Ends the run

While the onboarding marker is set, the new member hosts the party but does not confirm for it. The marker clears in steps 8 to 12.

The coordinator signs the namespace proposal in a temporary topology store, and publishes it at step 6. A host that never signs therefore leaves the namespace unchanged. The coordinator publishes the hosting proposal at step 4, because the new member’s import needs it in the new member’s own store. Canton keeps that proposal pending until the new member signs it.

The coordinator’s card can show these steps under their code names, for example “Export state”. Architecture lists the Canton calls behind each step.

  1. Check the party page. The new member is in Participants, and Owners has grown by one.
  2. Give the new member credentials. On the new member’s node, store the party credentials and grant the Canton rights. See the Party credentials section of Authentication and operator roles.
  3. Add the new member to governance. The topology change does not change the party’s GovernanceRules contract. If the party has one, propose a governance add-member action. See the Add a governance member section of Membership and governance changes.
  4. Raise the threshold if the plan requires it. Run Change Threshold to count the new member.

A participant that hosted the party before can still own its namespace. For example, it removed its own hosting entry, but stayed a namespace owner. Decentralization Manager detects this case and adds the hosting entry only. The namespace stays as it is.

In this case, the new threshold must equal the current threshold. Change it afterwards with Change Threshold.

Treat a participant that left the party after a failed run as a recovery case. Two rules apply:

  • Do not reconnect it while it lacks the party’s contracts. On reconnect, it replays every event that it missed. It judges each event by the topology at that event’s time. So it acts as a host again, and it crashes.
  • Purge only what the party alone holds. The participant purges the party’s old contracts before the re-add. Keep every contract that another party on that participant is also a stakeholder of. The copy in step 7 leaves those contracts out, so a contract that you purge by mistake never comes back.

Contact the BitSafe team before you recover a participant in this state.

Decentralization Manager refuses to start the run

Section titled “Decentralization Manager refuses to start the run”
Error says Do this
“is not a configured peer of this node” Add the new member as a peer on the coordinator
“No cached membership for …” Open Parties and search for the party, to refresh the list. Then start the run again
“is already a member of …” Nothing. The participant already hosts the party
“This node is not a member of …” Start the run from a node that hosts the party
“Cannot add yourself as the new participant” Start the run from the node of a current host, not from the new member
“new_threshold must be between 1 and N” Pick a value up to the current number of owners
“already has a … workflow in flight” Wait for that run to end, or cancel it
A list of incompatible peers Upgrade those nodes to the same release

The coordinator’s card shows the error. Click Retry on the coordinator, or call POST /workflows/{instance_name}/retry. The run continues from the step that failed.

Do not cancel the run. A cancel does not reconnect the new member. The coordinator cannot retry a cancelled run, so the state that a retry needs is gone.

Error says Cause Do this
“the new member … is missing N package(s)” A DAR is missing on the new member Distribute the DAR, then click Retry
“Re-hosting … leaves the namespace as it is” A former member was re-added with a new threshold Start a new run with the current threshold
“… is quarantined for …” An earlier copy failed after part of the contracts reached Canton See Quarantine
A timeout in RetireLegacyKeys Too few upgraded owners are online Bring the owners online, then click Retry
“peer(s) are marked complete but have no … artefact” The coordinator restarted during a hand-off and lost signatures Start a new run

A connected participant that hosts the party without its contracts receives the party’s traffic. That state has crashed a participant on MainNet. Re-adding a former member lists the rules that follow from it.

A copy can fail after some contracts already reached the new member’s participant. Canton cannot report how many arrived. Decentralization Manager then quarantines the new member for this party, and it refuses every later copy onto it.

  1. Repair the participant with Canton’s RepairCommitmentsUsingAcs, or restore it from a backup.

  2. Lift the quarantine on the new member’s node, which ran the import:

    Terminal window
    curl -sS -X DELETE \
    "$NEW_MEMBER_NODE/acs-import-quarantine?party_id=$PARTY&participant_id=$NEW_MEMBER" \
    -H "Authorization: Bearer $TOKEN"
  3. Start a new add-party run.

The DELETE call records your decision only. It repairs nothing. The call answers {"lifted": true} when it removed a quarantine.

Add the new member to governance: Membership and governance changes.