Consult the documentation for deeper understanding: https://docs.daml.com/canton/usermanual/identity_management.html#party-on-two-nodes.
Contributors:
- Docker with access to Digital Asset enterprise repository
- Maven
- Daml SDK
-
Build the project
mvn compile
-
Start
participantAdocker compose up -d participantA
Optionally you can override the environment variables with for example a
.env.localfile and use it like:docker compose --env-file .env.local up -d participantA
-
Setup
participantA- Allocate party
Alicedaml ledger allocate-parties Alice --host localhost --port 5011 - Upload the models DAR
daml ledger upload-dar --host localhost --port 5011 target/multi-node-canton-example-0.0.1.dar - Create one or more
MultiNode.Accountcontracts, e.g. using the navigatordaml navigator server localhost 5011 --port 7501 --feature-user-management false
- Allocate party
-
Start
participantBdocker compose up -d participantB
Optionally you can override the environment variables with for example a
.env.localfile and use it like:docker compose --env-file .env.local up -d participantB
-
Setup
partipantB- Upload the models DAR
-
Do the party migration
You need to run the following set of commands using respective interactive Canton consoles. You access the consoles by attaching to the Docker instances.
docker attach participantA
docker attach participantB
If you want to detach from a console use
Ctrl+P Ctrl+Qcombination as described in the Docker manual.Commands on
participantB:val alice = multiNodeDemo.parties.list().find(x => x.party.toString.contains("Alice")).get.party participantB.topology.party_to_participant_mappings.authorize(TopologyChangeOp.Add, alice, participantB.id, RequestSide.To, ParticipantPermission.Submission) participantA.topology.party_to_participant_mappings.authorize(TopologyChangeOp.Add, alice, participantB.id, RequestSide.From, ParticipantPermission.Submission)
Commands on
particpantA:// Using string values is not ideal, need a better solution. val alice = multiNodeDemo.parties.list().find(x => x.party.toString.contains("Alice")).get.party val timestamp = participantA.topology.party_to_participant_mappings.list(filterStore = "multiNodeDemo", filterParty = "Alice").map(_.context.validFrom).max participantA.repair.download(Set(alice), "/migration/alice.acs.gz", filterDomainId = "multiNodeDemo", timestamp = Some(timestamp))
Commands on
participantB:// This step is needed, otherwise `participantB` will not accept the ACS import. participantB.domains.connect(multiNodeDemo.defaultDomainConnection) // This step is needed, otherwise an error is thrown stating that `participantB` is still connected. participantB.domains.disconnect_all() repair.party_migration.step2_import_acs(participantB, "/migration/alice.acs.gz") participantB.domains.reconnect_all()
-
Try
participantBYou can confirm (e.g. via REPL) that contracts are visible.
daml repl --ledger-host localhost --ledger-port 5021 target/multi-node-canton-example-0.0.1.dar
In the Daml REPL run:
import MultiNode.Account listKnownParties let alice = partyFromText("Copy the party ID here.") accounts <- query @Account alice show accounts