By: Owen Stanford, Principal Software Engineer
If you’ve been reading the recent Corda 5 blog posts, you will already know that the architecture of Corda is changing. This change requires a re-think about the features that we offer to CorDapp developers, which are collectively known as Corda Services.
What are Corda Services and why do they exist?
In Corda 4, Service classes are long-lived instances that can trigger or be triggered by flows from within a node. A Service class is limited to a single instance per node. During startup, the node handles the creation of the service.
Flows are the main building block of any Corda application and while they are great for encapsulating a business process with defined lifecycles, applications often need to implement functionality that is complex to model as a flow. This is where Corda Services can be used. As stated above, a Corda Service is a long running instance of a class that shares the same lifecycle as the node itself. When the node creates a service, it passes an instance of the AppServiceHub to the service class. This gives the service access to the Corda APIs, enabling app developers to
write services for these common use cases:
- Common code – The most basic function of a service is to enable developers to encapsulate common code that can be shared by different types of flow.
- Shared data – As the Corda Service lives for the lifetime of the node, it can be used to store data that is shared between multiple flows or multiple invocations of the same flow.
- Vault observation – A Corda Service can subscribe to the stream of vault updates when the node starts. This allows developers to build feeds to external systems, create triggering logic for flows, or schedule future operations.
- Background task processing – Flows that need to execute a background task, such as calling out to a web service, can use the External Operations API to delegate work to a Corda Service. This enables other flows to execute while the background operation completes.
So what do Corda Services look like in Corda 5?
Well there’s no easy way to say it, but we won’t have Corda Services in Corda 5!! Ok, that’s not strictly true, but they won’t look anything like the services in Corda 4.x and the reason they won’t is interesting. As we said at the start, the fundamental architecture of Corda is changing in Corda 5. This change will support high availability and horizontal scaling, and will have an impact on how we support the features provided by Corda Services. The most important change for us is the introduction of virtual Nodes.
In Corda 5, a virtual Node encapsulates the logical execution context of a CorDapp (Identity, storage, network addressability etc.), but not the physical execution context. This is a departure from previous versions of Corda, where the logical node and the physical Node (JVM Process) are the same thing. Changing the Node in this way enables the platform to schedule the execution of flows across all available resources (workers) in the cluster. It is this distributed execution that enables Corda 5 to support high availability and horizontal scaling not available in Corda 4 (see this blog post for an in-depth look at Virtual Nodes in Corda 5). What this means in practice is that there is no guarantee that two flows for the same virtual node will execute in the same process. In fact it’s highly likely that a single flow could switch processes (workers) during a suspend/resume cycle. As you can see in the diagram above, breaking the affinity between Node and process means that we loose our ability for a node to host a long-running service that is accessible from all flows. This in turn means that the long-running Corda Service model used in previous version of Corda has to go.
For app developers using Corda 5, a new set of APIs and specialized platform services will be available to implement the features that would have previously been built with Corda Services. The diagram to the left shows how these services and APIs are now a part of the Corda 5 platform. They now share the benefits of high availability and horizontal scaling, which the distributed architecture enables.
New Services and APIs in Corda 5
Token selection and soft locking are key features for any CorDapp that wants to select states to spend. By allowing flows to “lock” the states it wants to spend, they can prevent other concurrent flows from selecting the same states. This minimizes the risk of a double spend, which causes transactions to fail during notarization. In Corda 4.x, token selection is provided by the Tokens SDK, which is built on top of Corda Services. For Corda 5, token selection will be provided as part of the platform and new APIs will allow flows to query for and claim a set of states for spending. This new service will work in conjunction with the new Ledger Hooks (see below) to allow app developers to control the states available for locking, as well as the criteria that their flows can use for selection.
Key Value Store
A common use case of the existing Corda Services is to share state between flows. In Corda 5 the platform will provide a simple, fast, key value store service for each Virtual Node. Flows for the same node are able to use a new set of APIs to read/write (with concurrency checks) application data to the store.
For example, a CorDapp may need to get a credit rating for a counterparty from an external system, which may be an expensive operation for a flow to make. In this case the Key Value Store could be used to cache the credit rating, thereby allowing subsequent flows to access it without making costly calls to an external system.
In Corda 5 a new framework is provided that allows an app developer to develop hooks, which are called in response to a change in the ledger. These replace the functionality provided by the old vault observables in Corda 4. The platform will provide different classes of hook for developers to use:
- Token Selection Hook – This hook will receive ledger transactions and output selectable tokens used by the Token Selection Service. For example, a CorDapp might want to make a currency state selectable via token selection. In this case the a hook could be used to filter which states are available for selection.
- External Event Hook – This hook allows developers to publish a messages to an external system (see External Connectivity below) in response to activity in the ledger. For example, a CorDapp might need to notify a regulatory system for transactions that fit a specific criteria. In this case a hook could be used to identify the transactions in scope and send them to the regulatory system.
- Scheduled Flow Start Hook – This hook enables developers to start a flow in response to a ledger event. The hook optionally enables the developer to specify a future data/time that the event should be delivered. This facilitates scheduling of future flows for individual states. For example, a CorDapp might need to make coupon payments on a bond at set intervals. In this case a hook could be used to schedule a payment flow to run on the specific coupon date.
For Corda to be useful in the real world, it’s important that it can interact with other systems . While the new HTTP API in Corda 5 provides a rich API for interacting with Corda from the outside world, there are many cases where CorDapps need to talk to the outside world from within. This is what the new External Connectivity API is designed for. The API allows Flows and Hooks to call out to external systems over two channels; a Kafka topic (or pair of topics) or an HTTP endpoint. For Kafka, developers can define their own Kafka topics that are addressable via the new API. For HTTP, developers can use the new APIs to address any URL accessible from the worker(s) running the External Connectivity Service.
- Kafka publish – Allows a Flow or Hook to publish a message to a user defined Kafka topic. For example, a CorDapp might want to publish summary data to a reporting system for completed transactions. In this case a hook or flow could publish the summary data for a reporting system to consume.
- Kafka request/response – Allows a Flow to publish a request message to a user defined Kafka topic and await a response on a user defined response topics. For example, a CorDapp might need approval from an external system before a payment can be made. In this case the flow could publish an approval request to the external system and wait for the response before continuing with the payment.
- HTTP request/response – Allows a Flow to invoke a simple REST endpoint and await the response. For example, a CordApp might want to check a Legal Entity Identifier(LEI) as part of a validation process, using publicly available data on the internet. In this case the a flow could use the API to perform an HTTP GET against a URL to retrieve the details for an LEI.
The exciting new architecture introduced by Corda 5 presents new opportunities for performance, scalability, reliability and deployment flexibility, allowing Corda Networks to make more efficient use of resources. These changes, as we can see for Corda Services, will require some of the existing development paradigms to be replaced.
We hope that this post has given you an overview of how we plan to provide app developers with the flexibility to build exciting new apps, capable of doing everything that they could in Corda 4 and more, even with the removal of the old custom Corda Services.
In the near future, we will publish a series of blog posts that describe each of these new services in detail, and how to use them.