Corda Open Source Edition 4.11 to 4.12 upgrade guide

This upgrade guide outlines the steps for migrating your Corda 4.11 node to version 4.12 while maintaining backwards compatibility with earlier Corda 4.x versions.

Corda 4.12 has been upgraded to use Kotlin 1.9.20 and Java 17. When designing Corda 4.12, we had to take into consideration the issue of having a backchain of transactions that had been verified using Kotlin 1.2 and Java 8 by earlier versions of Corda.

If a Corda 4.12 node were to be part of a network of mixed Corda 4.x versions, a Corda 4.12 node would not be able to verify a contract compiled using Kotlin 1.2. Similarly, a Corda node running an earlier version of Kotlin would not be able to verify a new Corda 4.12 contract compiled using Kotlin 1.9.20.

To address verification issues, both earlier versions of Corda 4.x and Corda 4.12 had to have a way of verifying the correct contract attachment, depending on the Corda version. This is where the external verifier, a component of Corda 4.12, comes in.

The external verifier is a process started by Corda 4.12, running Kotlin 1.2 (with Java 17). This enables Corda 4.12 to run independently of Java 8. Whenever Corda 4.12 detects an old contract version, it externally verifies this contract within the external verifier process.

When upgrading to Corda 4.12, the old contract CorDapp JAR is preserved and relocated to a new directory named legacy-contracts. This directory is essential in a mixed network (4.12 nodes and pre-4.12 nodes) as it provides legacy contracts for Corda 4.12 nodes to maintain backward compatibility, as required by the transaction builder.

The following diagram outlines the core differences between Corda 4.11 and Corda 4.12, providing a high-level overview of how the external verifier works with the legacy contract code to verify both Corda 4.11 and Corda 4.12 transactions.

The different colors in the diagram indicate the elements used in each version. While Corda 4.11 remains unchanged, some elements from Corda 4.11 are carried over to Corda 4.12. When the 4.12 node starts, it loads the 4.11 Contract CorDapp, enabling the Corda 4.12 node to send transactions to the Corda 4.11 node. Both the 4.11 contract code (pink) and the 4.12 contract code (green) are included in the transactions. The 4.11 node then discards the new 4.12 contract code.

The Corda 4.11 transaction verifier has also been preserved in an external process to allow Corda 4.11 transactions to be verified by Corda 4.12.

Corda 4.12 vs Corda 4.11
Corda 4.12 vs Corda 4.11

This section describes three possible upgrade paths to a network operating on Corda 4.12. In these scenarios a network is a collection of Corda nodes that are all running the same CorDapp.

All scenarios involving the upgrade of existing node versions from a previous version of Corda 4.x to Corda 4.12 assume the existence of 4.11 (or earlier) transactions in the node’s backchain.

In this scenario, you have a mixed network where only selected nodes are upgraded to Corda 4.12, while others remain on previous versions of Corda 4.x. This scenario requires you to perform the following actions:

  1. Upgrade any existing CorDapps to run on Java 17 and Kotlin 1.9.20.
  2. Keep a copy of the old CorDapp contract JAR file in the new legacy-contracts folder placed inside all upgraded 4.12 nodes.
  3. If your contracts depend on third-party dependencies or JARs from the drivers folder, then you must place these in the new legacy-jars folder located inside all upgraded 4.12 nodes.

Any future Corda 4.12 nodes added to the network will also require the legacy-contracts folder, unless all nodes have been updated by that time. In the latter case, you are adding new Corda 4.12 nodes to a non-mixed network and this requirement is no longer necessary.

Additionally, if contracts depend on third-party dependencies or JARs in the drivers folder, then the populated legacy-jars folder must exist on all 4.12 nodes.

In this scenario, you are creating a non-mixed network composed solely of nodes operating on Corda 4.12. Transactions occurring within this newly-upgraded network only have the 4.12 contract component group and therefore, you do not need the legacy-contracts folder. However, it is still important that you keep a copy of the old contract JAR for reference.

If any new Corda 4.12 nodes are added to this network in the future, a problem arises wherein new nodes won’t trust old contract attachments. For example, this happens if a new transaction contains a backchain of old Corda 4.x transactions. For this reason, you must upload the old contract JAR via RPC to the new node, ensuring it trusts the old contract version.

The legacy-jars folder is also required if contracts use third-party libraries or depend on JARs in the drivers directory.

This scenario is the simplest, as it does not require any complex update procedures. In this scenario, all CorDapps are developed for Java 17 and Kotlin 1.9.20, and the process for adding new nodes is the same as setting up a new network of any previous Corda version.

This guide assumes that you have a working Corda network with one or more Corda 4.11 nodes running. If you have custom CorDapps running on your nodes, this guide also describes the required upgrade steps for CorDapps from version 4.11 to 4.12.

To complete the upgrade from Corda 4.11 to Corda 4.12, you need the following components:

  • A Corda 4.12 JAR (obtained from R3).
  • Access to, and the ability to edit the source code for any existing custom CorDapps running in the nodes to be upgraded from 4.11 to 4.12.

To upgrade your Corda node from version 4.11 to 4.12, you must perform the following steps:

  1. Upgrade any custom CorDapps running on the Corda 4.11 node to work with Java 17 and Kotlin 1.9.20. See Upgrade 4.11 CorDapps.
  2. Validate all existing transactions (per node) to ensure that their backchain works with 4.12.
  3. Preserve old CorDapp contracts in a new folder called legacy-contracts. See Add the legacy contracts folder to mixed networks.
  4. If your contracts use third-party dependencies or rely on JARs in the drivers directory, then create a new folder legacy-jars and insert the third-party dependencies and required JARs from the drivers folder into the legacy-jars folder.

You must update all custom CorDapps being upgraded that are running on Corda 4.11 nodes so they use Java 17 and Kotlin 1.9.20. For steps on updating Cordapps, see Upgrading CorDapps to newer platform versions.

You must annotate any flow that initiates other flows with the @InitiatingFlow annotation, which is defined as:

annotation class InitiatingFlow(val version: Int = 1)

The version property, which defaults to 1, specifies the flow’s version. You must increment this integer value whenever a flow release includes changes that are not backwards compatible. However, in this case, the flow version must stay the same to ensure backward compatibility with the flows running on previous Corda versions. However, even though in this case you are not incrementing the flow version, you must always increment the new 4.12 contract version; see Contract versioning.

When Corda 4.12 starts, it loads the CorDapp contract JAR. For version 4.12, the contract version must be higher than the contract version in the legacy-contracts JAR file. Therefore, you must increment the contract version by at least one.

The new CorDapp should inherit the same minimum platform version as Corda 4.12, which is 140. This is not 14, to account for minor updates to Corda 4.11.

Upon startup, a node verifies the signing key for the CorDapps it uses, preventing unwanted code from being executed. In Corda 4.12, nodes having both new and legacy versions of a contract CorDapp must have the same signing keys, otherwise the node will fail to start.

When operating a network with nodes running different versions of Corda, you must store the old CorDapp contract JAR files in the Corda 4.12 node directory (see Legacy contracts). This step is not required if all nodes in your network are being upgraded to Corda 4.12.

However, in both scenarios, you must keep a copy of the old CorDapp contracts JAR file. This file may be required if new Corda 4.12 nodes are introduced into a network containing nodes that have previously been upgraded. For steps describing adding a new node to an existing network of Corda 4.12 containing previously upgraded nodes, see Adding new 4.12 nodes.

Corda 4.12 introduces the concept of legacy contracts. A new legacy-contracts folder is required when operating a network where not all nodes are running Corda 4.12.

This folder contains old CorDapp contract JAR files required by the external verifier process to verify old contract attachments in new transactions. The following is an example folder structure of how to set up the node folder to include the legacy-contracts folder.

Before upgrade:

.
├── certificates
├── corda-4.11.jar
├── cordapps
│   ├── config
│   ├── corda-finance-contracts-4.11.jar
│   └── corda-finance-workflows-4.11.jar
├── drivers
└── node.conf
After upgrade

After upgrade:

.
├── certificates
├── corda-4.12.jar
├── cordapps
│   ├── config
│   ├── corda-finance-contracts-4.12.jar
│   └── corda-finance-workflows-4.12.jar
├── drivers
├── legacy-contracts
│   └── corda-finance-contracts-4.11.jar
├── legacy-jars
│   └── third-party-dependency.jar
└── node.conf

To ensure compatibility, you must keep the legacy contracts. When a node operating on a prior version of Corda 4.x wants to transact with a Corda 4.12 node, the 4.12 node identifies an old contract version attached to the transaction. To verify this old contract, Corda 4.12 initiates the external verifier process, which starts a new external process running Kotlin 1.2. Making use of the external verifier process is the way in which a 4.12 node can verify transactions from 4.11 or earlier nodes.

Similarly, when a 4.12 node creates a transaction, it adds a 4.12 contract into a new component group of the transaction, reserving the existing component group for the 4.11 contract. Consequently, when a 4.11 contract gets attached to the transaction, it ends up with two sets of contract attachments (JARs): the legacy one and the new 4.12 contract. If this transaction is received by a node not running Corda 4.12, the node lacks awareness of the new component group. It disregards the 4.12 contract and proceeds to verify the legacy contract instead, which is then stored in the database.

Pre-4.12 transactions are verified in an external verifier process when encountered. By default, this process does not include all third-party libraries shipped with Corda 4.11 or earlier, nor does it have the contents of the drivers directory on its classpath. If your contracts in ledger attachments depend on such third-party libraries or items previously in the drivers directory of Corda 4.11 or earlier, you can place the required JAR files in a directory named legacy-jars within the node directory. Any JARs in this directory will be added to the classpath of the external verifier. The TVU will help you discover and verify resolution of such issues.

  1. Run the database migration scripts. See Use run-migration-scripts.

  2. Start your node in the usual way:

    java -jar corda-4.12.jar -f node.conf
    

If you want to add another Corda 4.12 node into your network post-upgrade, the specific steps vary depending on the state of your network.

If you are operating a mixed network, then the process for adding a new Corda 4.12 node is relatively straightforward.

  1. Set up the node folder structure same as other Corda 4.12 nodes.

  2. Add the legacy-contracts folder and associated files to the node folder.

  3. Add the legacy-jars folder if required.

    .
    ├── certificates
    ├── corda-4.12.jar
    ├── cordapps
    │   ├── config
    │   ├── corda-finance-contracts-4.12.jar
    │   └── corda-finance-workflows-4.12.jar
    ├── drivers
    ├── legacy-contracts
    │   └── corda-finance-contracts-4.11.jar
    ├── legacy-jars
    │   └── third-party-dependency.jar
    └── node.conf
    
  4. Register the node to the network and proceed to operate it as normal.

Perform the following steps if you are adding a new Corda 4.12 node to a network that is only running Corda 4.12 nodes, but also contains older Corda 4.x transactions.

  1. Set up the node folder structure without the legacy-contracts folder.

  2. Add the legacy-jars folder if required.

    .
    ├── certificates
    ├── corda-4.12.jar
    ├── cordapps
    │   ├── config
    │   ├── corda-finance-contracts-4.12.jar
    │   └── corda-finance-workflows-4.12.jar
    ├── legacy-jars
    │   └── third-party-dependency.jar
    ├── drivers
    └── node.conf
    
  3. Register and then start the node.

  4. Access the Corda node either via RPC client or the standalone shell and upload the old CorDapp contract JAR as an attachment to the node. For more information on uploading attachments, see Working with attachments.

In Corda 4.12, the Corda node explorer is no longer included in the release pack. Should you require it, the Corda 4.11 node explorer remains compatible with Corda 4.12 and should be used for Corda 4.12 nodes.

Corda 4.11 versions of the node and flow management plugins are also compatible with Corda 4.12 and you should use them for Corda 4.12 nodes.

After upgrading Corda to Java 17, CorDapps no longer have access to internal Java classes due to the strong encapsulation module system introduced in Java 11. If your CorDapp still requires access to any internal Java classes, you can open the package by either:

  • Starting the JAR with a command line option:

    java -jar corda.jar -f node.conf --add-opens $MODULE/$PACKAGE=$REFLECTING_MODULE
    
  • Or by declaring it in the CorDapp manifest file:

    Add-Opens: <module>/<package>
    

Was this page helpful?

Thanks for your feedback!

Chat with us

Chat with us on our #docs channel on slack. You can also join a lot of other slack channels there and have access to 1-on-1 communication with members of the R3 team and the online community.

Propose documentation improvements directly

Help us to improve the docs by contributing directly. It's simple - just fork this repository and raise a PR of your own - R3's Technical Writers will review it and apply the relevant suggestions.

We're sorry this page wasn't helpful. Let us know how we can make it better!

Chat with us

Chat with us on our #docs channel on slack. You can also join a lot of other slack channels there and have access to 1-on-1 communication with members of the R3 team and the online community.

Create an issue

Create a new GitHub issue in this repository - submit technical feedback, draw attention to a potential documentation bug, or share ideas for improvement and general feedback.

Propose documentation improvements directly

Help us to improve the docs by contributing directly. It's simple - just fork this repository and raise a PR of your own - R3's Technical Writers will review it and apply the relevant suggestions.