'Corda - Checking equality of AbstractParty, Party and AnonymousParty
In Corda we have the following type hierarchy for providing ledger identities:
abstract class AbstractParty(val owningKey: PublicKey): Destination {
/** Anonymised parties do not include any detail apart from owning key,
so equality is dependent solely on the key */
override fun equals(other: Any?): Boolean {
return other === this
|| other is AbstractParty
&& other.owningKey == owningKey
}
...
}
// Shortened for brevity
class Party(...) : AbstractParty(...) { ... }
class AnonymousParty(...) : AbstractParty(...) { ... }
Note the comment:
Anonymised parties do not include any detail apart from owning key, so equality is dependent solely on the key
What I want to know is, why is equality defined at the root of the hierarchy, but nowhere else?
For example:
val wellKnownAlice = Party(aliceKey, aliceX500name)
val anonymousAlice = AnonymousParty(aliceKey)
wellKnownAlice == anonymousAlice
// true
Whilst I hold an opinionated view, I don't feel like these should be equal when they are fundamentally different things. I feel like this would have been better implemented like so:
abstract class AbstractParty(val owningKey: PublicKey): Destination {
override fun equals(other: Any?): Boolean {
return other === this
|| other is AbstractParty
&& other.javaClass == javaClass
&& equalsByKey(other)
}
fun equalsByKey(other: AbstractParty): Boolean {
return other === this || other.owningKey == owningKey
}
...
}
class Party(...) : AbstractParty(...) {
override fun equals(other: Any?): Boolean {
return other === this
|| other is Party
&& other.name == name
&& equalsByKey(other)
}
...
}
class AnonymousParty(...) : AbstractParty(...) { ... }
Thoughts on this much appreciated.
Solution 1:[1]
I agree it is a bit of an inconsistency. I know you are a more experienced CorDapp developer than I am (because your previous questions have helped me learn Corda) but I will share my own experience.
When I first started working with Corda I thought (and coded) in terms of Party. However the more I introduced Confidential Identities into my CorDapps the more I began to think in terms of PublicKey (AnonymousParty).
So I actually find this “inconsistency” somewhat handy.
I wonder if the developers at R3 knew that CorDapps should generally always use AnonymousParty so wanted to make comparing AnonymousParty and Party as easy as possible. Just a guess.
Solution 2:[2]
Consider the case where you have name: CordaX500Name
and key: PublicKey
. Then define
val p1 = AnonymousParty(key)
val p2 = Party(name, key)
With your proposed implementation you would have p1 == p2
but not p2 == p1
, so the relation is not symmetric and hence not a valid equivalence relation.
The well-known name is supposed to be unique for any given key, so I think that the current implementation is reasonable. Otherwise we would distinguish otherwise equal identities based on whether they were resolved to a name or not.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Tywin Lannister |
Solution 2 | Ulrik Rasmussen |