When using a script to get a party by the partyID, can it only get the party belonging to the current node?

When using a script to get a party by the partyID, can it only get the party belonging to the current node?

When I have two participant nodes A and B, A has party wpp:AAAAAAAAA, B has party wpp:BBBBBBBB,
When I use the following script to get the wpp party of A, I will get the wrong one which belong to B. Can this script be optimized?

def allocateOrGetPartyUK(hint: String): PartyId =
  A.parties.list().find(_.party.uid.id == hint) match {
    case None => A.parties.enable(hint)
    case Some(p) => p.party
  }
  
val wpp= allocateOrGetPartyUK("wpp")

Hi @skylorna,

I am learning myself, so take this answer with a grain of salt
(ie. there may be a better way to do it!)

For a domain called mydomain

    // Setup
    A.domains.connect_local(mydomain)
    B.domains.connect_local(mydomain)
    val alice = A.parties.enable("Alice")
    val bob   = B.parties.enable("Bob")

party_on_A_filter can be applied to the domain topology, ppms to check for parties unique to that node

def a_parties(): List[PartyId] = 
{
    // Create filter
    val party_on_A_filter = (p2p:PartyToParticipant)=>p2p.participant.toProtoPrimitive.startsWith(A.id.toProtoPrimitive)

    // Party to participant mappings
    val ppms = mydomain.topology.party_to_participant_mappings.list()

    // Apply filter to mappings
    val result = ppms.filter(el=>party_on_A_filter(el.item)).map(_.item.party)
    result.toSet.toList
}

returns: res2: PartyId = Alice::AAAA

Usage with your example:

def allocateOrGetPartyUK(hint: String): PartyId =
  a_parties().find(_.party.uid.id == hint) match {
    case None => A.parties.enable(hint)
    case Some(p) => p.party
  }

Final note of caution:
Your example allows for parties with the same name to be created on different participant nodes. Just make sure this is what you really want to do


Try it and let us know how it works!

Michael Godfrey
DA Technical Support

Hi @mgodf89
I tried your way, but got error,
It seems that the return value of the a_parties() method cannot use the find(_.party.uid.id == hint) method, the type does not match

D:\Canton-2.6.3\bin>canton daemon -c remote-simple.conf --bootstrap create_party_user_new.canton
e[31mD:\Canton-2.6.3\bin\create_party_user_new.canton:35: value party is not a member of com.digitalasset.canton.topolog
y.PartyId
did you mean param?
    participant_hk_parties().find(_.party.uid.id == hint) match {
                                    ^e[39m
e[31mD:\Canton-2.6.3\bin\create_party_user_new.canton:37: type mismatch;
 found   : Any
 required: com.digitalasset.canton.topology.PartyId
    case Some(p) => p
                    ^e[39m
e[31mD:\Canton-2.6.3\bin\create_party_user_new.canton:45: value party is not a member of com.digitalasset.canton.topolog
y.PartyId
did you mean param?
    participant_uk_parties().find(_.party.uid.id == hint) match {
                                    ^e[39m
e[31mD:\Canton-2.6.3\bin\create_party_user_new.canton:47: type mismatch;
 found   : Any
 required: com.digitalasset.canton.topology.PartyId
    case Some(p) => p
                    ^e[39m
2023-08-25 16:48:20,900 [main] ERROR c.digitalasset.canton.ServerRunner - Bootstrap script terminated with an error: Com
pilation Failed

Because the environment is used by many teams, it is unavoidable to have partyIDs with the same name on different nodes, so I want to start with my own script to ensure that only the party on the node I want is fetched, and then used to assemble the user. this is what I really want to do

1 Like

Hi @skylorna ,

Thanks for the reply, I’ll test out your script when I get a chance.

This might be a few days however. If you are blocked in the meantime, I would just start peppering your script with .getClass tests

// Using .getClass to check return type
val ret_type = fn_under_test().getClass
println("Type of fn_under_test() is:  " + ret_type)

Once you know for certain what type to expect, drop in an assertion and leave it there no matter how obvious it may seem until the whole thing works as expected

assert (ret_val.getClass() == "expected type")

One final note, here’s a cleaner pattern for listing participant mappings:

def a_parties(): List[PartyId] = 
{
    // Party to participant mappings
    val ppms = mydomain.topology.party_to_participant_mappings.list()
    ppms.filter(_.item.participant.uid.id==A.uid.id).map(_.item.party).toSet.toList
}

Be sure to let us know what you find
Michael

@mgodf89
I used getClass, and their types are indeed different. My windows system prints out a bit of garbled characters, please don’t mind

@mgodf89
I found the problem, Need to modify the parameters in find()

this is wrong

def allocateOrGetPartyHK(hint: String): PartyId =
    participant_hk_parties().find(_.party.uid.id == hint) match {
    case None => participant_hk.parties.enable(hint)
    case Some(p) => p
  }

Just change it to this

def allocateOrGetPartyUK(hint: String): PartyId =
    participant_uk_parties().find(_.uid.id == hint) match {
    case None => participant_uk.parties.enable(hint)
    case Some(p) => p
  }

thanks for your help.

Ope - You’re right, that extra .map(_.item.party) changed the type
:partying_face:
Good catch!

1 Like