If a node wants to perform their own specific business logic within one side of a flow, how can this be implemented?
For example if a company wants to call an intern
Sure. I wrote a whole bunch of stuff on this I can paste here!
Structuring CorDapps
CorDapps can be split into shared and private elements:
Shared CorDapp elements
Typically, the shared elements of a CorDapp will include:
It is generally advisable to keep the shared CorDapp JARs as small as possible, this is because the JAR containing the state and contract definitions travels around the network with transactions containing states of the type defined in the JAR. Downstream verifiers of transactions may need to verify transactions containing states they do not transact with, so they don't need the flows on their class path. As such, it makes sense to package up the state and contract definitions (and any dependencies) separately to everything else.
Private CorDapp elements
Private elements of a corDapp usually comprise:
As mentioned above, CorDapp developers can share abstract representations of their flows and keep the implementation private. The flow framework allows parties to implement their own flows providing they conform to a common interface, this is, both the InitiatingFlow
and the InitiatedBy
flow send and receive the same types at the expected points in the flow.
As long as the flows do this, the rest of the implementation can be customised. For example, custom, private implementations might reach out to internal systems or use proprietary types, and as such, they should not be packaged with the shared elements of the CorDapp.
Flow versioning
In addition to the evolution of the platform, flows that run on top of the platform can also evolve. Any flow from which you want to initiate other flows must be annotated with the @InitiatingFlow
annotation, which is defined as:
annotation class InitiatingFlow(val version: Int = 1)
Note, the optional version property, which defaults to 1, to specify the version of the flow. This integer value, which for the moment, exists purely to guide developers, should be incremented whenever there is a release of a flow which has changes that are not backwards compatible with previous versions. A non-backwards compatible change is one that changes the interface of the flow.
Currently, handling flow versioning is left to the CorDapp developers. However, in the future the platform will implement prescribed rules.
What is the interface for a set of flows?
The flow interface defines the sequence of sends and receives between an InitiatingFlow and an InitiatedBy flow as well as the types sent and received. It is best illustrated with a sequence diagram:
In the diagram above, the InitiatingFlow:
The InitiatedBy flow does the opposite:
Providing both the IntiatingFlow
and the InitiatedBy
flows conform to the sequence defined by interface, the rest of the flows can be implemented in any way and can include proprietary business logic that is not shared with other parties. Indeed, this is the intended way to write flows.
For a example of actually how one would go about doing this, please look here: https://github.com/sollecitom/corda-foreign-exchange-example/blob/master/buyer-api/src/main/kotlin/net/corda/examples/fx/buyer/BuyCurrencyFlowDefinitions.kt
This was written by one of the Corda developers and in the file above, there is an abstract flow definition which has a private implementation known only to the buyer.