CorDapp Changes Introduced by Milestone 12

Posted on Posted in Blog
The following two tabs change content below.

Ross Nicoll

Ross is a developer working on the Corda platform within R3. He became interested in distributed ledger technology in late 2013, leading to him becoming one of the lead developers for Dogecoin Core and a contributor to Bitcoin Core.

Latest posts by Ross Nicoll (see all)

A large number of API improvements have been included in the Corda beta release (milestone 12), in preparation for API stabilisation later in the year. I wanted to talk about how those changes affect developers and how to migrate an existing CorDapp to Corda milestone 12. Note that for simplicity this post focuses on the changes from M11, so if upgrading a CorDapp from pre-M11 you will likely see further changes, please see the release notes and change log for full details. This post is intended for a technical audience, primarily developers working on CorDapps, and will be of limited interest to others.

From milestone 13 onwards we will be trying to reduce disruption from API changes; milestone 12 is disproportionately disruptive in order to get as many changes in at once, before stabilisation.

Flow Registration

In M11 flows were manually registered via the CorDapp’s plugin or via services, and are now found automatically via class path scanning on node startup. Flows must be annotated to inform Corda of how they are started, using the new annotations “@StartableByRPC” and “@InitiatedBy”, for flows which are started via RPC or via another flow, respectively.

Using the CorDapp tutorial as an example, the “ExampleFlow” contained two flows, “Initiator” and “Acceptor”. The both flows were previously registered via “requiredFlows” in ExamplePlugin, and the acceptor registered by “ExampleService” (which itself was listed in the “servicePlugins” field of “ExamplePlugin”). Plugins should no longer override either “requiredFlows” or “servicePlugins”, and these fields will be removed in a later release, instead flows are annotated to provide the same functionality.

To replace this we add the “@StartableByRPC” annotation to “ExampleFlow.Initiator” and the “@InitiatedBy” annotation to “ExampleFlow.Acceptor”. The updated flows look as follows (using the Kotlin example):

object ExampleFlow {
    @InitiatingFlow
    @StartableByRPC
    class Initiator(val iou: IOUState, val otherParty: Party): FlowLogic<SignedTransaction>() {
        …
    }

    @InitiatedBy(Initiator::class)
    class Acceptor(val otherParty: Party) : FlowLogic<Unit>() { 
        …
    }
}

The full source code of the updated example flow is available from https://github.com/corda/cordapp-tutorial/blob/master/kotlin-source/src/main/kotlin/com/example/flow/ExampleFlow.kt

Corda Services

Corda services, such as oracles, are also automatically detected on node startup by classpath scanning. Previously these had to be created in special classes via the “servicePlugins” method, with complex initiation logic using lazy values. This has now been simplified with the introduction of the “@CordaService” annotation. Any class annotated with this will be loaded as a Corda service singleton at startup, and flows will be able to get access to these singletons via the “ServiceHub.cordaService” method. An example of this new usage can be found here: https://github.com/corda/oracle-example/blob/master/service/src/main/kotlin/net/corda/examples/oracle/service/Oracle.kt

Identity

The identity APIs have been significantly reworked to enforce use of X.500 distinguished name for known parties, and to support the confidential (anonymised) identities. Notably:

  • Party names must be X.500 distinguished names. The “CN” and “L” (common name and location) attributes must be specified as a minimum, and “O” and “C” (organisation and country) are recommended. Note that common name is used as the short display name in a number of the examples, however for real CorDapps note that the full name must be available to users such that they can verify the identity correctly.
    • The “Party.name” field is now an “X500Name” object; this enforces the correct format, allows interrogation of individual attributes and ensures equality testing matches attributes correctly.
    • The “partyFromName()” function on the identity service and Corda RPC interface has been deprecated and replaced with “partyFromX500Name” which takes in an “X500Name” object.
  • “Party” and related classes have been moved to the “net.corda.core.identity” package, from “net.corda.core.crypto”.
  • There is a new “PartyAndCertificate” class which pairs a party with the X.509 certificate and certificate path to verify the identity of the party. This should generally not be required by CorDapps, however.

To update from earlier versions, the node name in node configuration files must be an X.500 distinguished name. Where the network map’s node name changes, ensure this is reflected in other node configurations as well.

Fields which contain public keys in “ContractState” implementations should be replaced with the “AbstractParty” type. This allows full “Party” objects or “AnonymousParty” to be used in a state, and is intended for a future milestone to enable automatic substitution of full parties for anonymised parties during transaction building. Classes such as “PartyAndReference” which previously contained a “Party” now contain “AbstractParty” instead.

Private Keys and Signatures

The last area of change is to remove the functionality for extracting private keys from the key management service. Previously this functionality was provided so the keys could be used for signing data, however this approach is incompatible with hardware security modules (HSM), which do not allow extraction of the private key from their internal stores. Data is now passed to the key management service, typically via the service hub, for signing.

Two new functions have been added to the service hub for use in signing transactions. “signInitialTransaction()” takes in a transaction builder and optional public keys to sign with, and returns the signed transaction. For adding a signature to a partially signed transaction, “addSignature()” takes in a signed transaction and optional public keys and returns a copy of the signed transaction with the new signature added. In both cases if no signing key is specified then the default legal identity of the node is used.

A third function “createSignature()” has been added to service hub, which exists to enable the two functions above. CorDapps are not expected to use this function directly.

CorDapps in Milestone 13 and Beyond

While we are still several releases away from Corda 1.0 and API stability, milestone 12 incorporates a large number of changes in order to minimise later disruption. Confidential identities will require further tweaks in order to guide the identity anonymisation/deanonymisation process. The core functionality for confidential identities is now in place and example flows are being currently updated to utilise these new APIs. Increasingly we are attempting to retain and deprecate previous APIs where making changes, in order to guide the upgrade process.

Comments

  1. Do we have any estimated timeline that Corda 1.0 would be released?

  2. End of September, I believe. Cheers

  3. Thanks Roger, do you have any idea what would be main new feature included in Corda 1.0?

Continue the discussion at discourse.corda.net

Participants