Canton: how to host a party on multiple participants

I am developing a simple Canton app with two participants, let’s say participant1 and participant2. I have one party, call them party0, that I want to be able to exercise choices and create contracts on both participants. I’ve started out by enabling party0 on participant2 like so:

val party0 = participant2.parties.enable("party0")

When I go to exercise a choice on a contract created on participant1 using com.daml:bindings-rxjava:1.14.0, I get an error like the following:

io.grpc.StatusRuntimeException: INVALID_ARGUMENT: MalformedRequest(CN10044-0): Malformed request; message=Confirmation request creation failed, reason=ParticipantAuthorizationError(PAR::participant1::1220891ca686... does not host party0::12204879eef15a1cec6c0ca615479e4e0c487f58840d919ae217fc9d38eb42b2f24d or is not active.)

When I try to authorize party0 on participant1 like so:

participant2.identity.party_to_participant_mappings.authorize(com.digitalasset.canton.identity.IdentityChangeOp.Add, None, party0, participant1)

I get the following error:

ERROR c.d.c.e.CommunityConsoleEnvironment - Request failed for participant2.
  GrpcServerError: INTERNAL/Mismatching namespaces 12209af0ca15... and 12209503ac31....
  Request: AuthorizePartyToParticipant(Add,None,Both,party0::12209af0ca15...,PAR::participant1::12209503ac31...,Submission)
  Trailers: Metadata(content-type=application/grpc)

Should I be able to have party0 exercise choices and create contracts on both participants? If so, how to I get the party hosted on both participants?

Thanks!

2 Likes

The participants are in different identity namespaces, that’s why you get the “Mismatching namespaces” error on your authorization command. You have to split the command into two to authorize both directions of the party to participant mapping.

First participant2 needs to authorize, because that participant owns the party’s namespace:

participant2.identity.party_to_participant_mappings.authorize(IdentityChangeOp.Add, party = party0, participant = participant1.id, side = RequestSide.From)

And then participant1 as the new hosting participant has to also authorize the other direction of the mapping:

participant1.identity.party_to_participant_mappings.authorize(IdentityChangeOp.Add, party = party0, participant = participant1.id, side = RequestSide.To)

Be aware that multi-participant parties have to be setup before any transactions for that party are processed. The feature to migrate an existing party with contracts from one participant to another does not exist yet.

3 Likes

Thanks so much for your response @soren ! That looks straightforward enough. I will give this a try and get back to you when I get a chance but it might take a bit because I have competing obligations.

2 Likes

When I try to run this first command:

participant2.identity.party_to_participant_mappings.authorize(
  IdentityChangeOp.Add,
  party = party0,
  participant = participant1.id,
  side = RequestSide.To)

I get an error like this:

ERROR c.d.c.e.CommunityConsoleEnvironment - Request failed for participant2.
  GrpcClientError: INVALID_ARGUMENT/IdentityManagerParentError(NoSigningKeyFor(Some(participant1),122052a98e83...))
  Request: AuthorizePartyToParticipant(Add,None,To,party0::122098d1c5d4...,PAR::participant1::122052a98e83...,Submission)
  Trailers: Metadata(content-type=application/grpc)
1 Like

Hey @sully,

Is that the only command that’s being run?

Btw have you seen the section of our user manual that contains an example for hosting a party on multiple participants? Looking at that I’d guess that side may need to be set to From.

1 Like

Thank you @davidpadbury , and thanks for the link!

Yes, we I switch the From and To from Soren’s answer, it works!

Yay!

2 Likes

Fixed @soren’s answer to reflect this, thanks!

2 Likes