If I had contract and state classes placed into two different cordapp jars.
I believe if I change the contract instead, old state object references the old contract attachment by hash will throw out an error of ContractConstraintRejection.
But if it's the other way around, when I change the state, i.e add a new parameter. Will it impact the anything?
Interesting question.
It will indeed impact the transaction once the node you're transacting with receives it.
This is because your state will still have the same class name on both nodes and when the other node receives the amended state, it won't know how to deserialize the modified state and throw an exception.
Related
I am trying to implement an Validator class in Contract-States library of CordApp, which have several validation methods that are inherited by Model classes in their init() fun, so that each time a Model class is called/initialized the validation happens on the spot.
Now I'm stuck at a point, where I need to validate whether the incoming member name(through a Model class) matches with Organisation name of the node, I need to access the NetworkMap for that. How can I do that?
In Work-Flow library each flow extends FlowLogic class that implements ServiceHub interface and through that we can access the NetworkMap, but how to do that in Contract-States library?
P.S. - I'm trying to avoid any circular dependency (Contract-States lib should not depend on Work-Flow lib)
The short answer, you can't.
The long answer:
The difference between flow validations and contract validation is that the latter (contracts) must be deterministic meaning for the same input they must always give the same output whether it's now or after 100 years, in the current node or any other node.
The reason for that is because any time (even in the future) when a node receives a transaction it must validate that transaction which includes validating the inputs which in return requires validating the transaction that created those inputs and so on, until you get a fully validated graph of all the inputs that lead to the outputs that were used as inputs and so on.
That's why the contract should return the same result any time, and that's why it should be deterministic, and that's why contracts (unlike flows) don't have access to external resources (like HTTP calls, or even the node's database).
Imagine if the contract was relying on the node's database for some validation rule, as you know, states are distributed on a need to know basis (i.e. only to participants of the state); so one node might have the state that you're using as validation source and another node won't, so the contract's output (transaction valid/invalid) will differ between nodes, and that breaks the deterministic concept.
Contracts only have access to the transaction components: inputs, outputs, attachments, signatures, time-windows, reference states.
Good news, there are other ways to implement your requirement:
Using an attachment that has the list of nodes that are allowed to be part of the transaction, this method should be used if the blacklist is not updated frequently and you can see the example here.
Using reference states, where you can create a state that has the allowed parties and require the existence of that reference state in your transaction; this method should be used when the blacklist is more frequently updated. You can read about reference states here.
Using Oracles, this option is in case there is a world organization (or for instance Ministry of Trade of some country) that provides an Oracle which returns the list of blacklisted parties; and you use that Oracle in your transaction. You can read about Oracles here.
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.
As I’m developing my first corDapp, I thought it might be useful to be able to reference a transaction’s initiator(flow starter) from the contract level. The reason being that although my contract is callable by any party, I don’t necessarily want to allow any party to call each command.
In my state, I have a list of what you might call admins. These admins should be the only ones that are able to issue commands on this list like RemoveAdmin() or AddAdmin().
Instead of being able to reject this command from contract level (which I think should done at this level because this is just another command constraint) based on a reference of who initiated it, I have to instead do it on the responder flow level.
Anyone else think an tx.initiator field might be useful for permission constraints like I described? If not, why is it better to do it at the responder flow level?
I think the conceptual issue is that, in Corda, transactions can be collaboratively constructed - eg if two parties are exchanging assets and the partial tx gets passed around so they can populate it with their respective inputs. So there isn’t always a proposer/initiator conceptually. So the concept doesn’t exist on Corda’s data model.
That being said, you can take three approaches:
Since you don't care about who proposed the transaction, rather that it was done by an admin you can configure the non-proposing admins only to sign a tx if they see it has been signed by another admin. So none of the non-proposers will sign it until the actual proposer has.
Make the proposer/initiator of the transaction part of your State object and check that this proposer/initiator is in your Admin list.
Throw an exception if the initiator of the flow is not in the admin list:
//make sure that the party running this flow is already an admin
if(ourIdentity !in AdminInputStateRef.state.data.participants){
throw IllegalArgumentException("The initiator of this flow must be a admin.")
}
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.
Good examples of how attachments are meant to be used include:
Calendar data
Fixes (e.g. LIBOR)
Smart contract code
In what way can I leverage on attachment to parameterise values or even codify custom agreement rules so contract can validate using it?
i.e
"Custom contract code must pass." using openAttachment(hashId).run == true
I want to be able to create a state that has a template of rules, but at the same time, able to handle custom (any) new rules proposed by initiator, and accepted by counterparties.
Contract code is attached automatically. These are the contracts that are assigned to a state when adding state as an output within a transaction.
These would be the standard "template of rules" that everyone has pre-agreed to in the development of the CorDapp and are run by everyone to reach consensus.
In theory, you could add a custom contract in an attachment, have counterparties upload the contract class to their nodes and then run verify against them by calling verify explicitly against the class within the flow. I suspect you'd have to have counterparty nodes stop and restart to load the class dynamically onto the classpath though.