George Hawkins
George Hawkins

Reputation: 38784

Enforcing the uniqueness of property values across Corda states of the same type?

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

Answers (3)

Joel
Joel

Reputation: 23140

There are several downsides to delegating this work to a notary:

  • It constitutes a privacy leak by forcing the use of a validating notary. In most deployments, you would want to use non-validating notaries
  • It means that only special notaries running custom flows can be used to notarise these SSN transactions
  • It rules out some distributed notary algorithms, since all the notaries in the cluster would have to reach consensus on SSN uniqueness as well as transaction uniqueness

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

George Hawkins
George Hawkins

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 @Columndocumentation 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

ltheron
ltheron

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

Related Questions