Reputation: 38784
How do I ensure that a property of a state is unique for all instances of that state on the ledger?
Say I have a PersonState
with properties name
and ssn
(social security number), how can one ensure that no PersonState
is ever written to the ledger that has the same ssn
value as any PersonState
already existing on the ledger?
If PersonState
was a DB table and name
and ssn
were columns then it would be easy to specify a uniqueness constraint on ssn
but I can't see how to do this with Corda.
The proposer of a new transaction, that would result in a new PersonState
ending up on the ledger, can obviously check the existing states when constructing the proposal. But this only confirms uniqueness at the time of the initial proposal - I don't see how one can ensure that things remain unique during the lifetime of the related flow such that the value is still guaranteed to be unique right through to the end of the finality flow (or guaranteed to be rejected at this point if it is no longer unique)?
I was trying to think if one could implement some kind of unique values service via an oracle of if a notary could somehow enforce this? Maybe I could come up with something around these ideas (probably with some fatal logical flaw) but if Corda already has some established process for this kind of thing then that would obviously be better.
PS yes, I know that storing SSNs to a ledger would probably be a bad idea, this is just an example.
Upvotes: 0
Views: 207
Reputation: 23140
There are several downsides to delegating this work to a notary:
I'd prefer an oracle in this case. The oracle would keep an internal database of allocated SSNs, and only sign transactions where the SSNs had not been used before. You could use tear-offs to prevent the oracle from seeing the rest of the transaction (see https://docs.corda.net/key-concepts-oracles.html#hiding-data), so privacy would be preserved.
The oracle would only have to sign issuances - contract rules could then ensure that the SSN on a state isn't modified once it has been issued.
Upvotes: 0
Reputation: 38784
User @Anoop posted an answer that was deleted for reasons that are unclear to me. The following is an expansion of his answer.
The Corda API docs for persistence describe how you can use JPA to specify how your states are mapped to the underlying vault DB.
They use the PersistentCashState
as an example - if you look at it you see:
class PersistentCashState(
/** X500Name of owner party **/
@Column(name = "owner_name")
var owner: AbstractParty,
@Column(name = "pennies")
var pennies: Long,
...
Note: The above is Kotlin rather than Java.
As you can see the @Column
annotation is used - if you look at the @Column
documentation you'll see you can use it to mark the column as unique with unique=true
:
Whether the column is a unique key. This is a shortcut for the UniqueConstraint annotation at the table level and is useful for when the unique key constraint corresponds to only a single column. This constraint applies in addition to any constraint entailed by primary key mapping and to constraints specified at the table level.
I haven't tried this to see how it works in practice. Using such a constraint would only make sense if you're using a Notary - as only a Notary can guarantee an ordering that will be respected by all parties. I.e. if you don't use a Notary one party might validly commit one transaction involving a state with a given ssn
while another party might first commit a different transaction involving the same ssn
.
I'm not sure what happens when the Notary tries the FinalityFlow
and then fails at the point of persisting the state to the DB. But this approach sounds less subject to race conditions than anything else I've seen so far (i.e. checking the vault first and then hoping nothing in another thread beats you to persisting a state involving a value that should be unique), i.e. it sounds like it should achieve the required transactionality.
Upvotes: 0
Reputation: 301
I think you'll need to check for uniqueness of this ssn
within the Flow of a Validating Notary.
Each time you receive a transaction, you check the double spend with a Notary in Corda, so in this case he would just check, at each step of the FLow, that he haven't already received the PersonState
state with a special rule applied to this ssn
.
Note that it would leak this data to the notary.
Upvotes: 0