Corda - Reference States and "current-ness" - corda

The R3 documentation for Reference States states that:
A reference input state is a ContractState which can be referred to in
a transaction by the contracts of input and output states but whose
contract is not executed as part of the transaction verification
process and is not consumed when the transaction is committed to the
ledger but is checked for “current-ness”. In other words, the contract
logic isn’t run for the referencing transaction only. It’s still a
normal state when it occurs in an input or output position.
With regards to checking for "current-ness" does this mean that you can only reference unspent/unconsumed states, or can you also reference spent/consumed states as well?

When a transaction containing states in the references list is sent to a notary, the notary will check whether those states (StateRefs) in the references list have been spent. If they have been spent (i.e. they are not current) then the notary will not sign. If they have not been spent (the StateRefs have not been spent), then they are current and the notary will sign the transaction, assuming all inputs (if present) are current and the transaction is notarised within the boundaries of the supplied time window.
You cannot include states which are already known to be spent in the references list. The assumption here is that the data will be stale so cannot be relied upon.
The state pointer feature assumes that you will not be referencing data known to be stale. If you do need to intentionally reference an old state then embed the StateRef directly in your state. You will have to manually ensure that all parties which need the StateRef, have it.

Related

Request StateStatus from a Notary

Is there any way a CorDapp can ask a Notary if a state has been consumed prior to using it in a Transaction?
Background:
I am testing FungibleToken’s that point to EvolvableTokenType’s. Eventually the EvolvableTokenType changes and holders of the tokens that are not Participants of the EvolvableTokenType end up with states in their vault that have been unknowingly consumed. When they try to execute a transaction involving these states the Notary will refuse to sign because it knows the states have been consumed.
I have written flows that will contact a Participant and request the missing state(s). However it would be more efficient if I could first ask the Notary if I need to do that (i.e. if the state hasn’t been consumed I don’t need to ask a participant for an update).
You could do this a couple ways.
For example, in your vault query, you could simply make sure to filter on StateStatus = UNCONSUMED. That's one way you can ensure this works the way you expect and you never get a state that won't fit your criteria.
check out this section of the docs on vaultQuery : https://docs.corda.net/docs/corda-os/4.7/api-vault-query.html#querycriteria-interface
The other way I'd recommend that might also work is just to include this filter in your contract verification for the transaction, but doing it at the flow level just catches the problem sooner rather than later.

how to hide properties of a transaction state based on status

I have started working on Corda recently. We have got the requirements not to show State properties for specific status.
While going through the document I have found some reference below but could not find any suitable example.
https://solutions.corda.net/corda-modelling-notation/views/views-common-concepts.html
Properties
These are the properties of the State whilst in the particular status. Not all properties need to be shown, just the ones salient to the behaviour of the State in this Status.
Could you be able to point me to any relevant example for the same?
Corda States are available to participants on a need-to-know basis and as a whole. The participant list returned by the getParticipants() method of a state defines the participants who should be aware of that state. You could update the participant list (add or remove) to grant or revoke access to a state but it's not possible to grant/revoke access to a part of the state.
To cater to your scenario below possible approaches can be taken:
Refactor your entire state into separate states and make them available to parties depending on the status.
Handle this on the application layer, after fetching the state from the Corda node and restrict visibility on the basis of the state.
Update the state variables to null based on the status, this may not be very feasible but just in case your use-case allows this.

Whats the best way to generate ledger change Events that include the Transaction Command?

The goal is to generate events on every participating node when a state is changed that includes the business action that caused the change. In our case, Business Action maps to the Transaction command and provides the business intent or what the user is doing in business terms. So in our case, where we are modelling the lifecycle of a loan, an action might be to "Close" the loan.
We model Event at a state level as follows: Each Event encapsulates a Transaction Command and is uniquely identified by a (TxnHash, OutputIndex) and a created/consumed status.
We would prefer a polling mechanism to generate events on demand, but an asynch approach to generate events on ledger changes would be acceptable. Either way our challenge is in getting the Command from the Transaction.
We considered querying the States using the Vault Query API vaultQueryBy() for the polling solution (or vaultTrackBy() for the asynch Obvservalble Stream solution). We were able to create a flow that gets the txn for a state. This had to be done in a flow, as Corda deprecated the function that would have allowed us to do this in our Springboot client. In the client we use vaultQueryBy() to get a list of States. Then we call a flow that iterates over the states, gets txHash from each StateRef and then calls serviceHub.validatedTransactions.getTransaction(txHash) to get signedTransaction from which we can ultimately retrieve the Command. Is this the best or recommended approach?
Alternatively, we have also thought of generating events of the Transaction by querying for transactions and then building the Event for each input and output state in the transaction. If we go this route what's the best way to query transactions from the vault? Is there an Observable Stream-based option?
I assume this mapping of states to command is a common requirement for observers of the ledger because it is standard to drive contract logic off the transaction command and quite natural to have the command map to the user intent.
What is the best way to generate events that encapsulate the transaction command for each state created or consumed on the ledger?
If I understand correctly you're attempting to get a notified when certain types of ledger updates occur (open, approved, closed, etc).
First: Asynchronous notifications are best practice in Corda, polling should be avoided due to the added weight it puts on the node for constant querying and delays. Corda provides several mechanisms for Observables which you can use: https://docs.corda.net/api/kotlin/corda/net.corda.core.messaging/-corda-r-p-c-ops/vault-track-by.html
Second: Avoid querying transactions from the database as these are intended to be internal to the node. See this answer for background on why to avoid transaction querying. In general only tables that begin with "VAULT_*" are intended to be queried.
One way to solve your use case would be a "status" field which reflects the command that was used to produce the current state. For example: if a "Close" command was used to produce the state it's status field could be "closed". This way you could use the above vaultTrackBy to look at each state's status field and infer the action that occured.
Just to finish up on my comment: While the approach met the requirements, The problem with this solution is that we have to add and maintain our own code across all relevant states to capture transaction-level information that is already tracked by the platform. I would think a better solution would be for the platform to provide consumers access to transaction-level information (selectively perhaps) just as it does for states. After all, the transaction is, in part, a business/functional construct that is meaningful at the client application level. For example, If I am "transferring" a loan, that may be a complex business transaction that involves many input and output states and may be an important construct/notion for the client application to manage.

How can I check whether a state is existed globally in Corda?

I have a state with a global ID. I want to check whether the state is already issued by other node before I issue the state.
Is there a way I can check the state on the whole chain or I have to notify all of the nodes about issuing new state?
Corda's privacy model means that there is no central "chain" that can be checked for an existing state with the same ID.
If you simply need a unique ID for your state, use something like UniqueIdentifier, ideally by implementing the LinearState interface (https://docs.corda.net/api-states.html#linearstate). UniqueIdentifier contains a 128-bit unique identifier. This is large enough to avoid collisions between all the LinearStates on the network, despite there being no centralised repository of allocated IDs.
If this is not good enough, and the IDs have to be allocated based on some scheme instead of randomly, you'll need to create some centralised oracle node that tracks issued IDs and only signs transactions where the ID being allocated has not been used before.

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.
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.
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.
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.

Resources