corda blockchain

Corda Blockchain Decentralized App

In this tutorial, we run an example Decentralized Application or DApp that uses Corda R3. This sample project comes with default Corda library, so it is great place for starting and learning Codra blockchain development.

To follow and better understand this tutorial, reading What is a Cordapp and How it Works is highly recommended. Also, after finishing this tutorial, you can move on to Develop your first Decentralized Application using Corda Distributed Ledger tutorial.

The example CorDapp allows nodes to agree IOUs with each other, as long as they obey the following contract rules:

  • The IOU’s value is strictly positive
  • A node is not trying to issue an IOU to itself

We will deploy and run the CorDapp on four test nodes:

  • Notary, which runs a notary service
  • PartyA
  • PartyB
  • PartyC

Because data is only propagated on a need-to-know basis, any IOUs agreed between PartyA and PartyB become “shared facts” between PartyA and PartyB only. PartyC won’t be aware of these IOUs.

Downloading the example CorDapp
Start by downloading the example CorDapp from GitHub:

  • Set up your machine by following the quickstart guide
  • Clone the samples repository from using the following command: git clone https://github.com/corda/samples
  • Change directories to the cordapp-example folder: cd samples/cordapp-example


Opening the example CorDapp in IntelliJ

Let’s open the example CorDapp in IntelliJ IDEA:

  • Open IntelliJ
  • A splash screen will appear. Click open, navigate to and select the cordapp-example folder, and click OK
  • Once the project is open, click File, then Project Structure. Under Project SDK:, set the project SDK by clicking New…, clicking JDK, and navigating to C:\Program Files\Java\jdk1.8.0_XXX on Windows or Library/Java/JavaVirtualMachines/jdk1.8.XXX on MacOSX (where XXX is the latest minor version number). Click Apply followed by OK
  • Again under File then Project Structure, select Modules. Click +, then Import Module, then select the cordapp-example folder and click Open. Choose to Import module from external model, select Gradle, click Next then Finish (leaving the defaults) and OK
  • Gradle will now download all the project dependencies and perform some indexing. This usually takes a minute or so

Project structure
The example CorDapp has the following structure:
.
├── LICENCE
├── README.md
├── TRADEMARK
├── build.gradle
├── clients
│   ├── build.gradle
│   └── src
│       └── main
│           ├── kotlin
│           │   └── com
│           │       └── example
│           │           └── server
│           │               ├── MainController.kt
│           │               ├── NodeRPCConnection.kt
│           │               └── Server.kt
│           └── resources
│               ├── application.properties
│               └── public
│                   ├── index.html
│                   └── js
│                       └── angular-module.js
├── config
│   ├── dev
│   │   └── log4j2.xml
│   └── test
│       └── log4j2.xml
├── contracts-java
│   ├── build.gradle
│   └── src
│       └── main
│           └── java
│               └── com
│                   └── example
│                       ├── contract
│                       │   └── IOUContract.java
│                       ├── schema
│                       │   ├── IOUSchema.java
│                       │   └── IOUSchemaV1.java
│                       └── state
│                           └── IOUState.java
├── contracts-kotlin
│   ├── build.gradle
│   └── src
│       └── main
│           └── kotlin
│               └── com
│                   └── example
│                       ├── contract
│                       │   └── IOUContract.kt
│                       ├── schema
│                       │   └── IOUSchema.kt
│                       └── state
│                           └── IOUState.kt
├── cordapp-example.iml
├── gradle
│   └── wrapper
│       ├── gradle-wrapper.jar
│       └── gradle-wrapper.properties
├── gradle.properties
├── gradlew
├── gradlew.bat
├── lib
│   ├── README.txt
│   └── quasar.jar
├── settings.gradle
├── workflows-java
│   ├── build.gradle
│   └── src
│       ├── integrationTest
│       │   └── java
│       │       └── com
│       │           └── example
│       │               └── DriverBasedTests.java
│       ├── main
│       │   └── java
│       │       └── com
│       │           └── example
│       │               └── flow
│       │                   └── ExampleFlow.java
│       └── test
│           └── java
│               └── com
│                   └── example
│                       ├── NodeDriver.java
│                       ├── contract
│                       │   └── IOUContractTests.java
│                       └── flow
│                           └── IOUFlowTests.java
└── workflows-kotlin
├── build.gradle
└── src
├── integrationTest
│   └── kotlin
│       └── com
│           └── example
│               └── DriverBasedTests.kt
├── main
│   └── kotlin
│       └── com
│           └── example
│               └── flow
│                   └── ExampleFlow.kt
└── test
└── kotlin
└── com
└── example
├── NodeDriver.kt
├── contract
│   └── IOUContractTests.kt
└── flow
└── IOUFlowTests.kt
The key files and directories are as follows:

  • The root directory contains some gradle files, a README and a LICENSE
  • config contains log4j2 configs
  • gradle contains the gradle wrapper, which allows the use of Gradle without installing it yourself and worrying about which version is required
  • lib contains the Quasar jar which rewrites our CorDapp’s flows to be checkpointable
  • clients contains the source code for spring boot integration
  • contracts-java and workflows-java contain the source code for the example CorDapp written in Java
  • contracts-kotlin and workflows-kotlin contain the same source code, but written in Kotlin. CorDapps can be developed in either Java and Kotlin

Running the example CorDapp
There are two ways to run the example CorDapp:

  • Via the terminal
  • Via IntelliJ

Both approaches will create a set of test nodes, install the CorDapp on these nodes, and then run the nodes. You can read more about how we generate nodes here.
Running the example CorDapp from the terminal
Building the example CorDapp

  • Open a terminal window in the cordapp-example directory
  • Run the deployNodes Gradle task to build four nodes with our CorDapp already installed on them:
    • Unix/Mac OSX: ./gradlew deployNodes
    • Windows: gradlew.bat deployNodes

Note
CorDapps can be written in any language targeting the JVM. In our case, we’ve provided the example source in both Kotlin and Java. Since both sets of source files are functionally identical, we will refer to the Kotlin version throughout the documentation.

  • After the build finishes, you will see the following output in the workflows-kotlin/build/nodes folder:
    • A folder for each generated node
    • A runnodes shell script for running all the nodes simultaneously on osX
    • A runnodes.bat batch file for running all the nodes simultaneously on Windows
  • Each node in the nodes folder will have the following structure:

. nodeName
├── additional-node-infos  //
├── certificates
├── corda.jar              // The Corda node runtime
├── cordapps               // The node’s CorDapps
│   ├── corda-finance-contracts-4.1.jar
│   ├── corda-finance-workflows-4.1.jar
│   └── cordapp-example-0.1.jar
├── drivers
├── logs
├── network-parameters
├── node.conf              // The node’s configuration file
├── nodeInfo-<HASH>        // The hash will be different each time you generate a node
└── persistence.mv.db      // The node’s database

Note

deployNodes is a utility task to create an entirely new set of nodes for testing your CorDapp. In production, you would instead create a single node as described in Creating nodes locally and build your CorDapp JARs as described in Building and installing a CorDapp.

Running the example CorDapp
Start the nodes by running the following command from the root of the cordapp-example folder:

  • Unix/Mac OSX: workflows-kotlin/build/nodes/runnodes
  • Windows: call workflows-kotlin\build\nodes\runnodes.bat

Each Spring Boot server needs to be started in its own terminal/command prompt, replace X with A, B and C:

  • Unix/Mac OSX: ./gradlew runPartyXServer
  • Windows: gradlew.bat runPartyXServer

Look for the Started ServerKt in X seconds message, don’t rely on the % indicator.

Warning

On Unix/Mac OSX, do not click/change focus until all seven additional terminal windows have opened, or some nodes may fail to start.
For each node, the runnodes script creates a node tab/window:
______               __
/ ____/     _________/ /___ _
/ /     __  / ___/ __  / __ `/         Top tip: never say “oops”, instead
/ /___  /_/ / /  / /_/ / /_/ /          always say “Ah, Interesting!”
\____/     /_/   \__,_/\__,_/

— Corda Open Source corda-4.1 (4157c25) ———————————————–

 

Logs can be found in                    : /Users/joeldudley/Desktop/cordapp-example/workflows-kotlin/build/nodes/PartyA/logs
Database connection url is              : jdbc:h2:tcp://localhost:59472/node
Incoming connection address             : localhost:10005
Listening on port                       : 10005
Loaded CorDapps                         : corda-finance-corda-4.1, cordapp-example-0.1, corda-core-corda-4.1
Node for “PartyA” started up and registered in 38.59 sec

 

Welcome to the Corda interactive shell.
Useful commands include ‘help’ to see what is available, and ‘bye’ to shut down the node.

Fri Mar 02 17:34:02 GMT 2018>>>
It usually takes around 60 seconds for the nodes to finish starting up. To ensure that all the nodes are running, you can query the ‘status’ end-point located at http://localhost:[port]/api/status (e.g. http://localhost:50005/api/status for PartyA).

Running the example CorDapp from IntelliJ

  • Select the Run Example CorDapp – Kotlin run configuration from the drop-down menu at the top right-hand side of the IDE
  • Click the green arrow to start the nodes:

Corda blockchain development

  • To stop the nodes, press the red square button at the top right-hand side of the IDE, next to the run configurations


Interacting with the example CorDapp

Via HTTP
The Spring Boot servers run locally on the following ports:

  • PartyA: localhost:50005
  • PartyB: localhost:50006
  • PartyC: localhost:50007

These ports are defined in clients/build.gradle.
Each Spring Boot server exposes the following endpoints:

  • /api/example/me
  • /api/example/peers
  • /api/example/ious
  • /api/example/create-iou with parameters iouValue and partyName which is CN name of a node

There is also a web front-end served from the home web page e.g. localhost:50005.
Warning
The content is only available for demonstration purposes and does not implement anti-XSS, anti-XSRF or other security techniques. Do not use this code in production.

Creating an IOU via the endpoint
An IOU can be created by sending a PUT request to the /api/example/create-iou endpoint directly, or by using the the web form served from the home directory.
To create an IOU between PartyA and PartyB, run the following command from the command line:
curl -X PUT ‘http://localhost:50005/api/example/create-iou?iouValue=1&partyName=O=PartyB,L=New%20York,C=US’
Note that both PartyA’s port number (50005) and PartyB are referenced in the PUT request path. This command instructs PartyA to agree an IOU with PartyB. Once the process is complete, both nodes will have a signed, notarised copy of the IOU. PartyC will not.

Submitting an IOU via the web front-end
To create an IOU between PartyA and PartyB, navigate to the home directory for the node, click the “create IOU” button at the top-left of the page, and enter the IOU details into the web-form. The IOU must have a positive value. For example:
Counterparty: Select from list
Value (Int):   5
And click submit. Upon clicking submit, the modal dialogue will close, and the nodes will agree the IOU.

Checking the output
Assuming all went well, you can view the newly-created IOU by accessing the vault of PartyA or PartyB:
Via the HTTP API:

  • PartyA’s vault: Navigate to http://localhost:50005/api/example/ious
  • PartyB’s vault: Navigate to http://localhost:50006/api/example/ious

Via home page:

  • PartyA: Navigate to http://localhost:50005 and hit the “refresh” button
  • PartyB: Navigate to http://localhost:50006 and hit the “refresh” button

The vault and web front-end of PartyC (at localhost:50007) will not display any IOUs. This is because PartyC was not involved in this transaction.

Via the interactive shell (terminal only)
Nodes started via the terminal will display an interactive shell:
Welcome to the Corda interactive shell.
Useful commands include ‘help’ to see what is available, and ‘bye’ to shut down the node.

Fri Jul 07 16:36:29 BST 2017>>>
Type flow list in the shell to see a list of the flows that your node can run. In our case, this will return the following list:
com.example.flow.ExampleFlow$Initiator
net.corda.core.flows.ContractUpgradeFlow$Authorise
net.corda.core.flows.ContractUpgradeFlow$Deauthorise
net.corda.core.flows.ContractUpgradeFlow$Initiate
net.corda.finance.flows.CashExitFlow
net.corda.finance.flows.CashIssueAndPaymentFlow
net.corda.finance.flows.CashIssueFlow
net.corda.finance.flows.CashPaymentFlow
net.corda.finance.internal.CashConfigDataFlow

Creating an IOU via the interactive shell
We can create a new IOU using the ExampleFlow$Initiator flow. For example, from the interactive shell of PartyA, you can agree an IOU of 50 with PartyB by runningflow start ExampleFlow$Initiator iouValue: 50, otherParty: “O=PartyB,L=New York,C=US”.
This will printout the following progress steps:

  • Generating transaction based on new IOU.
  • Verifying contract constraints.
  • Signing transaction with our private key.
  • Gathering the counterparty’s signature.
  • Collecting signatures from counterparties.
  • Verifying collected signatures.
  • Obtaining notary signature and recording transaction.
  • Requesting signature by notary service
      • Requesting signature by Notary service
      • Validating response from Notary service
  • Broadcasting transaction to participants
  • Done


Checking the output
We can also issue RPC operations to the node via the interactive shell. Type run to see the full list of available operations.
You can see the newly-created IOU by running run vaultQuery contractStateType: com.example.state.IOUState.
As before, the interactive shell of PartyC will not display any IOUs.

Via the h2 web console
You can connect directly to your node’s database to see its stored states, transactions and attachments. To do so, please follow the instructions in Node database.

Running nodes across machines
The nodes can be configured to communicate as a network even when distributed across several machines:

  • Deploy the nodes as usual:
    • Unix/Mac OSX: ./gradlew deployNodes
    • Windows: gradlew.bat deployNodes
  • Navigate to the build folder (workflows-kotlin/build/nodes)
  • For each node, open its node.conf file and change localhost in its p2pAddress to the IP address of the machine where the node will be run (e.g. p2pAddress=”10.18.0.166:10007″)
  • These changes require new node-info files to be distributed amongst the nodes. Use the network bootstrapper tool (see Network Bootstrapper) to update the files and have them distributed locally:

java -jar network-bootstrapper.jar workflows-kotlin/build/nodes

  • Move the node folders to their individual machines (e.g. using a USB key). It is important that none of the nodes – including the notary – end up on more than one machine. Each computer should also have a copy of runnodes and runnodes.bat.

For example, you may end up with the following layout:

    • Machine 1: Notary, PartyA, runnodes, runnodes.bat
    • Machine 2: PartyB, PartyC, runnodes, runnodes.bat
  • After starting each node, the nodes will be able to see one another and agree IOUs among themselves


Warning

The bootstrapper must be run after the node.conf files have been modified, but before the nodes are distributed across machines. Otherwise, the nodes will not be able to communicate.

Note
If you are using H2 and wish to use the same h2port value for two or more nodes, you must only assign them that value after the nodes have been moved to their individual machines. The initial bootstrapping process requires access to the nodes’ databases and if two nodes share the same H2 port, the process will fail.

Testing your CorDapp
Corda provides several frameworks for writing unit and integration tests for CorDapps.

Contract tests
You can run the CorDapp’s contract tests by running the Run Contract Tests – Kotlin run configuration.

Flow tests
You can run the CorDapp’s flow tests by running the Run Flow Tests – Kotlin run configuration.

Integration tests
You can run the CorDapp’s integration tests by running the Run Integration Tests – Kotlin run configuration.

Running tests in IntelliJ
See Running tests in IntelliJ

CorDapp samples

There are two distinct sets of samples provided with Corda, one introducing new developers to how to write CorDapps, and more complex worked examples of how solutions to a number of common designs could be implemented in a CorDapp. The former can be found on the Corda website. In particular, new developers should start with the example CorDapp.
The advanced samples are contained within the samples/ folder of the Corda repository. The most generally useful of these samples are:

  • The trader-demo, which shows a delivery-vs-payment atomic swap of commercial paper for cash
  • The attachment-demo, which demonstrates uploading attachments to nodes
  • The bank-of-corda-demo, which shows a node acting as an issuer of assets (the Bank of Corda) while remote client applications request issuance of some cash on behalf of a node called Big Corporation

Documentation on running the samples can be found inside the sample directories themselves, in the README.md file.
Note
If you would like to see flow activity on the nodes type in the node terminal flow watch.

Structuring a CorDapp & its Modules

The source code for a CorDapp is divided into one or more modules, each of which will be compiled into a separate JAR. Together, these JARs represent a single CorDapp. Typically, a Cordapp contains all the classes required for it to be used standalone. However, some Cordapps are only libraries for other Cordapps and cannot be run standalone.
A common pattern is to have:

  • One module containing only the CorDapp’s contracts and/or states, as well as any required dependencies
  • A second module containing the remaining classes that depend on these contracts and/or states

This is because each time a contract is used in a transaction, the entire JAR containing the contract’s definition is attached to the transaction. This is to ensure that the exact same contract and state definitions are used when verifying this transaction at a later date. Because of this, you will want to keep this module, and therefore the resulting JAR file, as small as possible to reduce the size of your transactions and keep your node performant.
However, this two-module structure is not prescriptive:

  • A library CorDapp containing only contracts and states would only need a single module
  • In a CorDapp with multiple sets of contracts and states that do not depend on each other, each independent set of contracts and states would go in a separate module to reduce transaction size
  • In a CorDapp with multiple sets of contracts and states that do depend on each other, either keep them in the same module or create separate modules that depend on each other
  • The module containing the flows and other classes can be structured in any way because it is not attached to transactions

Template CorDapps

You should base your project on one of the following templates:

  • Java Template CorDapp (for CorDapps written in Java)
  • Kotlin Template CorDapp (for CorDapps written in Kotlin)

Please use the branch of the template that corresponds to the major version of Corda you are using. For example, someone building a CorDapp on Corda 4.1 should use the release-V4 branch of the template.

Build system

The templates are built using Gradle. A Gradle wrapper is provided in the wrapper folder, and the dependencies are defined in the build.gradle files.
No templates are currently provided for Maven or other build systems.

Modules

The templates are split into two modules:

  • A cordapp-contracts-states module containing the contracts and states
  • A cordapp module containing the remaining classes that depends on the cordapp-contracts-states module

These modules will be compiled into two JARs – a cordapp-contracts-states JAR and a cordapp JAR – which together represent the Template CorDapp.

Module one – cordapp-contracts-states

Here is the structure of the src directory for the cordapp-contracts-states module of the Java template:

.
└── main
    └── java
        └── com
            └── template
                ├── TemplateContract.java
                └── TemplateState.java

The directory only contains two class definitions:

  • TemplateContract
  • TemplateState

These are definitions for classes that we expect to have to send over the wire. They will be compiled into their own CorDapp.

Module two – cordapp

Here is the structure of the src directory for the cordapp module of the Java template:

.
├── main
│   ├── java
│   │   └── com
│   │       └── template
│   │           ├── TemplateApi.java
│   │           ├── TemplateClient.java
│   │           ├── TemplateFlow.java
│   │           ├── TemplateSerializationWhitelist.java
│   │           └── TemplateWebPlugin.java
│   └── resources
│       ├── META-INF
│       │   └── services
│       │       ├── net.corda.core.serialization.SerializationWhitelist
│       │       └── net.corda.webserver.services.WebServerPluginRegistry
│       ├── certificates
│       └── templateWeb
├── test
│   └── java
│       └── com
│           └── template
│               ├── ContractTests.java
│               ├── FlowTests.java
│               └── NodeDriver.java
└── integrationTest
    └── java
        └── com
            └── template
                └── DriverBasedTest.java

The src directory is structured as follows:

  • main contains the source of the CorDapp
  • test contains example unit tests, as well as a node driver for running the CorDapp from IntelliJ
  • integrationTest contains an example integration test

Within main, we have the following directories:

  • java, which contains the source-code for our CorDapp:
    • TemplateFlow.java, which contains a template FlowLogic subclass
    • TemplateState.java, which contains a template ContractState implementation
    • TemplateContract.java, which contains a template Contract implementation
    • TemplateSerializationWhitelist.java, which contains a template SerializationWhitelist implementation
    • TemplateApi.java, which contains a template API for the deprecated Corda webserver
    • TemplateWebPlugin.java, which registers the API and front-end for the deprecated Corda webserver
    • TemplateClient.java, which contains a template RPC client for interacting with our CorDapp
  • resources/META-INF/services, which contains various registries:
    • net.corda.core.serialization.SerializationWhitelist, which registers the CorDapp’s serialisation whitelists
    • net.corda.webserver.services.WebServerPluginRegistry, which registers the CorDapp’s web plugins
  • resources/templateWeb, which contains a template front-end

In a production CorDapp:

  • We would remove the files related to the deprecated Corda webserver (TemplateApi.java, TemplateWebPlugin.java, resources/templateWeb, and net.corda.webserver.services.WebServerPluginRegistry) and replace them with a production-ready webserver
  • We would also move TemplateClient.java into a separate module so that it is not included in the CorDapp

Building and installing a CorDapp

CorDapps run on the Corda platform and integrate with it and each other. This article explains how to build CorDapps. To learn what a CorDapp is, please read What is a CorDapp?.

CorDapp format

A CorDapp is a semi-fat JAR that contains all of the CorDapp’s dependencies except the Corda core libraries and any other CorDapps it depends on.
For example, if a Cordapp depends on corda-core, your-other-cordapp and apache-commons, then the Cordapp JAR will contain:

  • All classes and resources from the apache-commons JAR and its dependencies
  • Nothing from the other two JARs

Build tools

In the instructions that follow, we assume you are using Gradle and the cordapp plugin to build your CorDapp. You can find examples of building a CorDapp using these tools in the Kotlin CorDapp Template and the Java CorDapp Template.
To ensure you are using the correct version of Gradle, you should use the provided Gradle Wrapper by copying across the following folder and files from the Kotlin CorDapp Template or the Java CorDapp Template to the root of your project:

  • gradle/
  • gradlew
  • gradlew.bat

Setting your dependencies

Choosing your Corda, Quasar and Kotlin versions

Several ext variables are used in a CorDapp’s build.gradle file to define version numbers that should match the version of Corda you’re developing against:

  • ext.corda_release_version defines the version of Corda itself
  • ext.corda_gradle_plugins_version defines the version of the Corda Gradle Plugins
  • ext.quasar_version defines the version of Quasar, a library that we use to implement the flow framework
  • ext.kotlin_version defines the version of Kotlin (if using Kotlin to write your CorDapp)

The current versions used are as follows:

ext.corda_release_version = '4.1'
ext.corda_gradle_plugins_version = '4.0.42'
ext.quasar_version = '0.7.10'
ext.kotlin_version = '1.2.71'

In certain cases, you may also wish to build against the unstable Master branch.
Corda dependencies
The cordapp plugin adds three new gradle configurations:

  • cordaCompile, which extends compile
  • cordaRuntime, which extends runtime
  • cordapp, which extends compile

cordaCompile and cordaRuntime indicate dependencies that should not be included in the CorDapp JAR. These configurations should be used for any Corda dependency (e.g. corda-core, corda-node) in order to prevent a dependency from being included twice (once in the CorDapp JAR and once in the Corda JARs). The cordapp dependency is for declaring a compile-time dependency on a “semi-fat” CorDapp JAR in the same way as cordaCompile, except that Cordformation will only deploy CorDapps contained within the cordapp configuration.
Here are some guidelines for Corda dependencies:

  • When building a CorDapp, you should always include net.corda:corda-core:$corda_release_version as a cordaCompile dependency, and net.corda:corda:$corda_release_version as a cordaRuntime dependency
  • When building an RPC client that communicates with a node (e.g. a webserver), you should include net.corda:corda-rpc:$corda_release_version as a cordaCompiledependency.
  • When you need to use the network bootstrapper to bootstrap a local network (e.g. when using Cordformation), you should include net.corda:corda-node-api:$corda_release_version as either a cordaRuntime or a runtimeOnly dependency. You may also wish to include an implementation of SLF4J as a runtimeOnly dependency for the network bootstrapper to use.
  • To use Corda’s test frameworks, add net.corda:corda-test-utils:$corda_release_version as a testCompile dependency. Never include corda-test-utils as a compileor cordaCompile dependency.
  • Any other Corda dependencies you need should be included as cordaCompile dependencies.

Here is an overview of the various Corda dependencies:

  • corda – The Corda fat JAR. Do not use as a compile dependency. Required as a cordaRuntime dependency when using Cordformation
  • corda-confidential-identities – A part of the core Corda libraries. Automatically pulled in by other libraries
  • corda-core – Usually automatically included by another dependency, contains core Corda utilities, model, and functionality. Include manually if the utilities are useful or you are writing a library for Corda
  • corda-core-deterministic – Used by the Corda node for deterministic contracts. Not likely to be used externally
  • corda-djvm – Used by the Corda node for deterministic contracts. Not likely to be used externally
  • corda-finance-contracts, corda-finance-workflows and deprecated corda-finance. Corda finance CorDapp, use contracts and flows parts respectively. Only include as a cordaCompile dependency if using as a dependent Cordapp or if you need access to the Corda finance types. Use as a cordapp dependency if using as a CorDapp dependency (see below)
  • corda-jackson – Corda Jackson support. Use if you plan to serialise Corda objects to and/or from JSON
  • corda-jfx – JavaFX utilities with some Corda-specific models and utilities. Only use with JavaFX apps
  • corda-mock – A small library of useful mocks. Use if the classes are useful to you
  • corda-node – The Corda node. Do not depend on. Used only by the Corda fat JAR and indirectly in testing frameworks. (If your CorDapp _must_ depend on this for some reason then it should use the compileOnly configuration here – but please don’t do this if you can possibly avoid it!)
  • corda-node-api – The node API. Required to bootstrap a local network
  • corda-node-driver – Testing utility for programmatically starting nodes from JVM languages. Use for tests
  • corda-rpc – The Corda RPC client library. Used when writing an RPC client
  • corda-serialization – The Corda core serialization library. Automatically included by other dependencies
  • corda-serialization-deterministic – The Corda core serialization library. Automatically included by other dependencies
  • corda-shell – Used by the Corda node. Never depend on directly
  • corda-test-common – A common test library. Automatically included by other test libraries
  • corda-test-utils – Used when writing tests against Corda/Cordapps
  • corda-tools-explorer – The Node Explorer tool. Do not depend on
  • corda-tools-network-bootstrapper – The Network Builder tool. Useful in build scripts
  • corda-tools-shell-cli – The Shell CLI tool. Useful in build scripts
  • corda-webserver-impl – The Corda webserver fat JAR. Deprecated. Usually only used by build scripts
  • corda-websever – The Corda webserver library. Deprecated. Use a standard webserver library such as Spring instead

Dependencies on other CorDapps

Your CorDapp may also depend on classes defined in another CorDapp, such as states, contracts and flows. There are two ways to add another CorDapp as a dependency in your CorDapp’s build.gradle file:

  • cordapp project(“:another-cordapp”) (use this if the other CorDapp is defined in a module in the same project)
  • cordapp “net.corda:another-cordapp:1.0” (use this otherwise)

The cordapp gradle configuration serves two purposes:

  • When using the cordformation Gradle plugin, the cordapp configuration indicates that this JAR should be included on your node as a CorDapp
  • When using the cordapp Gradle plugin, the cordapp configuration prevents the dependency from being included in the CorDapp JAR

Note that the cordformation and cordapp Gradle plugins can be used together.

Other dependencies

If your CorDapps have any additional external dependencies, they can be specified like normal Kotlin/Java dependencies in Gradle. See the example below, specifically the apache-commons include.

Signing the CorDapp JAR

The cordapp plugin can sign the generated CorDapp JAR file using JAR signing and verification tool. Signing the CorDapp enables its contract classes to use signature constraints instead of other types of the constraints, for constraints explanation refer to API: Contract Constraints. By default the JAR file is signed by Corda development certificate. The signing process can be disabled or configured to use an external keystore. The signing entry may contain the following parameters:

  • enabled the control flag to enable signing process, by default is set to true, set to false to disable signing
  • options any relevant parameters of SignJar ANT task, by default the JAR file is signed with Corda development key, the external keystore can be specified, the minimal list of required options is shown below, for other options referer to SignJar task:
    • keystore the path to the keystore file, by default cordadevcakeys.jks keystore is shipped with the plugin
    • alias the alias to sign under, the default value is cordaintermediateca
    • storepass the keystore password, the default value is cordacadevpass
    • keypass the private key password if it’s different than the password for the keystore, the default value is cordacadevkeypass
    • storetype the keystore type, the default value is JKS

The parameters can be also set by system properties passed to Gradle build process. The system properties should be named as the relevant option name prefixed with ‘signing.’, e.g. a value for alias can be taken from the signing.alias system property. The following system properties can be used: signing.enabled, signing.keystore, signing.alias, signing.storepass, signing.keypass, signing.storetype. The resolution order of a configuration value is as follows: the signing process takes a value specified in the signing entry first, the empty string “” is also considered as the correct value. If the option is not set, the relevant system property named signing.option is tried. If the system property is not set then the value defaults to the configuration of the Corda development certificate.
The example cordapp plugin with plugin signing configuration:

cordapp {
    signing {
        enabled true
        options {
            keystore "/path/to/jarSignKeystore.p12"
            alias "cordapp-signer"
            storepass "secret1!"
            keypass "secret1!"
            storetype "PKCS12"
        }
    }
    //...

CorDapp auto-signing allows to use signature constraints for contracts from the CorDapp without need to create a keystore and configure the cordapp plugin. For production deployment ensure to sign the CorDapp using your own certificate e.g. by setting system properties to point to an external keystore or by disabling signing in cordapp plugin and signing the CordDapp JAR downstream in your build pipeline. CorDapp signed by Corda development certificate is accepted by Corda node only when running in the development mode. In case CordDapp signed by the (default) development key is run on node in the production mode (e.g. for testing), the node may be set to accept the development key by adding the cordappSignerKeyFingerprintBlacklist = [] property set to empty list (see Configuring a node).
Signing options can be contextually overwritten by the relevant system properties as described above. This allows the single build.gradle file to be used for a development build (defaulting to the Corda development keystore) and for a production build (using an external keystore). The example system properties setup for the build process which overrides signing options:

./gradlew -Dsigning.keystore="/path/to/keystore.jks" -Dsigning.alias="alias" -Dsigning.storepass="password" -Dsigning.keypass="password"

Without providing the system properties, the build will sign the CorDapp with the default Corda development keystore:

./gradlew

CorDapp signing can be disabled for a build:

./gradlew -Dsigning.enabled=false

Other system properties can be explicitly assigned to options by calling System.getProperty in cordapp plugin configuration. For example the below configuration sets the specific signing algorithm when a system property is available otherwise defaults to an empty string:

cordapp {
    signing {
        options {
            sigalg System.getProperty('custom.sigalg','')
        }
    }
    //...

Then the build process can set the value for custom.sigalg system property and other system properties recognized by cordapp plugin:

./gradlew -Dcustom.sigalg="SHA256withECDSA" -Dsigning.keystore="/path/to/keystore.jks" -Dsigning.alias="alias" -Dsigning.storepass="password" -Dsigning.keypass="password"

To check if CorDapp is signed use JAR signing and verification tool:

jarsigner --verify path/to/cordapp.jar

Cordformation plugin can also sign CorDapps JARs, when deploying set of nodes, see Creating nodes locally.
If your build system post-processes the Cordapp JAR, then the modified JAR content may be out-of-date or not complete with regards to a signature file. In this case you can sign the Cordapp as a separate step and disable the automatic signing by the cordapp plugin. The cordapp plugin contains a standalone task signJarwhich uses the same signing configuration. The task has two parameters: inputJars – to pass JAR files to be signed and an optional postfix which is added to the name of signed JARs (it defaults to “-signed”). The signed JARs are returned as outputJars property.
For example in order to sign a JAR modified by modifyCordapp task, create an instance of the net.corda.plugins.SignJar task (below named as sign). The output of modifyCordapp task is passed to inputJars and the sign task is run after modifyCordapp one:

task sign(type: net.corda.plugins.SignJar) {
    inputJars modifyCordapp
}
modifyCordapp.finalizedBy sign
cordapp {
    signing {
        enabled false
    }
    //..
}

The task creates a new JAR file named *-signed.jar which should be used further in your build/publishing process. Also the best practice is to disable signing by the cordapp plugin as shown in the example.

Example

Below is a sample CorDapp Gradle dependencies block. When building your own CorDapp, use the build.gradle file of the Kotlin CorDapp Template or the Java CorDapp Template as a starting point.

dependencies {
    // Corda integration dependencies
    cordaCompile "net.corda:corda-core:$corda_release_version"
    cordaCompile "net.corda:corda-finance-contracts:$corda_release_version"
    cordaCompile "net.corda:corda-finance-workflows:$corda_release_version"
    cordaCompile "net.corda:corda-jackson:$corda_release_version"
    cordaCompile "net.corda:corda-rpc:$corda_release_version"
    cordaCompile "net.corda:corda-node-api:$corda_release_version"
    cordaCompile "net.corda:corda-webserver-impl:$corda_release_version"
    cordaRuntime "net.corda:corda:$corda_release_version"
    cordaRuntime "net.corda:corda-webserver:$corda_release_version"
    testCompile "net.corda:corda-test-utils:$corda_release_version"

    // Corda Plugins: dependent flows and services
    // Identifying a CorDapp by its module in the same project.
    cordapp project(":cordapp-contracts-states")
    // Identifying a CorDapp by its fully-qualified name.
    cordapp "net.corda:bank-of-corda-demo:1.0"

    // Some other dependencies
    compile "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
    testCompile "org.jetbrains.kotlin:kotlin-test:$kotlin_version"
    testCompile "junit:junit:$junit_version"

    compile "org.apache.commons:commons-lang3:3.6"
}

Creating the CorDapp JAR

Once your dependencies are set correctly, you can build your CorDapp JAR(s) using the Gradle jar task

  • Unix/Mac OSX: ./gradlew jar
  • Windows: gradlew.bat jar

Each of the project’s modules will be compiled into its own CorDapp JAR. You can find these CorDapp JARs in the build/libs folders of each of the project’s modules.
Warning
The hash of the generated CorDapp JAR is not deterministic, as it depends on variables such as the timestamp at creation. Nodes running the same CorDapp must therefore ensure they are using the exact same CorDapp JAR, and not different versions of the JAR created from identical sources.
The filename of the JAR must include a unique identifier to deduplicate it from other releases of the same CorDapp. This is typically done by appending the version string to the CorDapp’s name. This unique identifier should not change once the JAR has been deployed on a node. If it does, make sure no one is relying on FlowContext.appName in their flows..

Installing the CorDapp JAR

Note
Before installing a CorDapp, you must create one or more nodes to install it on. For instructions, please see Creating nodes locally.
At start-up, nodes will load any CorDapps present in their cordapps folder. In order to install a CorDapp on a node, the CorDapp JAR must be added to the <node_dir>/cordapps/ folder (where node_dir is the folder in which the node’s JAR and configuration files are stored) and the node restarted.

CorDapp configuration files

CorDapp configuration files should be placed in <node_dir>/cordapps/config. The name of the file should match the name of the JAR of the CorDapp (eg; if your CorDapp is called hello-0.1.jar the config should be config/hello-0.1.conf).
Config files are currently only available in the Typesafe/Lightbend config format. These files are loaded during node startup.
CorDapp configuration can be accessed from CordappContext::config whenever a CordappContext is available. For example:

@StartableByRPC
class GetStringConfigFlow(private val configKey: String) : FlowLogic<String>() {
    object READING : ProgressTracker.Step("Reading config")
    override val progressTracker = ProgressTracker(READING)

    @Suspendable
    override fun call(): String {
        progressTracker.currentStep = READING
        val config = serviceHub.getAppContext().config
        return config.getString(configKey)
    }
}

Using CorDapp configuration with the deployNodes task

If you want to generate CorDapp configuration when using the deployNodes Gradle task, then you can use the cordapp or projectCordapp properties on the node. For example:

task deployNodes(type: net.corda.plugins.Cordform, dependsOn: ['jar']) {
    nodeDefaults {
        // this external CorDapp will be included in each project
        cordapp("$corda_release_group:corda-finance-contracts:$corda_release_version")
        // this external CorDapp will be included in each project with the given config
        cordapp("$corda_release_group:corda-finance-workflows:$corda_release_version") {
            config "issuableCurrencies = [ USD ]"
        }
    }
    node {
        name "O=Bank A,L=London,C=GB"c
        ...
        // This adds configuration for another CorDapp project within the build
        cordapp (project(':my-project:workflow-cordapp')) {
            config "someStringValue=test"
        }
        cordapp(project(':my-project:another-cordapp')) {
            // Use a multiline string for complex configuration
            config '''
                someStringValue=test
                anotherStringValue=10
             '''
        }
    }
    node {
        name "O=Bank B,L=New York,C=US"
        ...
        // This adds configuration for the default CorDapp for this project
        projectCordapp {
            config project.file("src/config.conf")
        }
    }
}

There is an example project that demonstrates this in the samples folder of the Corda Git repository, called cordapp-configuration . API documentation can be found at api/kotlin/corda/net.corda.core.cordapp/index.html.

Minimum and target platform version

CorDapps can advertise their minimum and target platform version. The minimum platform version indicates that a node has to run at least this version in order to be able to run this CorDapp. The target platform version indicates that a CorDapp was tested with this version of the Corda Platform and should be run at this API level if possible. It provides a means of maintaining behavioral compatibility for the cases where the platform’s behavior has changed. These attributes are specified in the JAR manifest of the CorDapp, for example:

'Min-Platform-Version': 4
'Target-Platform-Version': 4

Defaults

  • Target-Platform-Version (mandatory) is a whole number and must comply with the rules mentioned above.
  • Min-Platform-Version (optional) will default to 1 if not specified.

Using the cordapp Gradle plugin, this can be achieved by putting this in your CorDapp’s build.gradle:

cordapp {
    targetPlatformVersion 4
    minimumPlatformVersion 4
}

Separation of CorDapp contracts, flows and services

It is recommended that contract code (states, commands, verification logic) be packaged separately from business flows (and associated services). This decoupling enables contracts to evolve independently from the flows and services that use them. Contracts may even be specified and implemented by different providers (eg. Corda currently ships with a cash financial contract which in turn is used in many other flows and many other CorDapps).
As of Corda 4, CorDapps can explicitly differentiate their type by specifying the following attributes in the JAR manifest:

'Cordapp-Contract-Name'
'Cordapp-Contract-Version'
'Cordapp-Contract-Vendor'
'Cordapp-Contract-Licence'

'Cordapp-Workflow-Name'
'Cordapp-Workflow-Version'
'Cordapp-Workflow-Vendor'
'Cordapp-Workflow-Licence'

Defaults
Cordapp-Contract-Name (optional) if specified, the following Contract related attributes are also used:

  • Cordapp-Contract-Version (mandatory), must be a whole number starting from 1.
  • Cordapp-Contract-Vendor (optional), defaults to UNKNOWN if not specified.
  • Cordapp-Contract-Licence (optional), defaults to UNKNOWN if not specified.

Cordapp-Workflow-Name (optional) if specified, the following Workflow related attributes are also used:

  • Cordapp-Workflow-Version (mandatory), must be a whole number starting from 1.
  • Cordapp-Workflow-Vendor (optional), defaults to UNKNOWN if not specified.
  • Cordapp-Workflow-Licence (optional), defaults to UNKNOWN if not specified.

As with the general CorDapp attributes (minimum and target platform version), these can be specified using the Gradle cordapp plugin as follows:
For a contract only CorDapp we specify the contract tag:

cordapp {
    targetPlatformVersion 4
    minimumPlatformVersion 3
    contract {
        name "my contract name"
        versionId 1
        vendor "my company"
        licence "my licence"
    }
}

For a CorDapp that contains flows and/or services we specify the workflow tag:

cordapp {
    targetPlatformVersion 4
    minimumPlatformVersion 3
    workflow {
        name "my workflow name"
        versionId 1
        vendor "my company"
        licence "my licence"
    }
}


Note

It is possible, but not recommended, to include everything in a single CorDapp jar and use both the contract and workflow Gradle plugin tags.

Warning
Contract states may optionally specify a custom schema mapping (by implementing the Queryable interface) in its contracts JAR. However, any associated database schema definition scripts (eg. Liquibase change set XML files) must currently be packaged in the flows JAR. This is because the node requires access to these schema definitions upon start-up (contract JARs are now loaded in a separate attachments classloader). This split also caters for scenarios where the same contract CorDapp may wish to target different database providers (and thus, the associated schema DDL may vary to use native features of a particular database). The finance CorDapp provides an illustration of this packaging convention. Future versions of Corda will de-couple this custom schema dependency to remove this anomaly.

CorDapp Contract Attachments

As of Corda 4, CorDapp Contract JARs must be installed on a node by a trusted uploader, either by

  • installing manually as per Installing the CorDapp JAR and re-starting the node.
  • uploading the attachment JAR to the node via RPC, either programmatically or via the Node shell by issuing the following command:

>>> run uploadAttachment jar: path/to/the/file.jar
Contract attachments that are received from a peer over the p2p network are considered untrusted and will throw a UntrustedAttachmentsException exception when processed by a listening flow that cannot resolve that attachment from its local attachment storage. The flow will be aborted and sent to the nodes flow hospital for recovery and retry. The untrusted attachment JAR will be stored in the nodes local attachment store for review by a node operator. It can be downloaded for viewing using the following CRaSH shell command:
>>> run openAttachment id: <hash of untrusted attachment given by `UntrustedAttachmentsException` exception
Should the node operator deem the attachment trustworthy, they may then issue the following CRaSH shell command to reload it as trusted:
>>> run uploadAttachment jar: path/to/the/trusted-file.jar
and subsequently retry the failed flow (currently this requires a node re-start).

Note

This behavior is to protect the node from executing contract code that was not vetted. It is a temporary precaution until the Deterministic JVM is integrated into Corda whereby execution takes place in a sandboxed environment which protects the node from malicious code.
By now, you have good understanding of what is distributed ledger and how Corda Decentralized Applications or DApps work. Specifically, Corda comes with few default sample projects and templates that we reviewed in depth in this tutorial. For the next step, we develop our first DApp via Develop your first Decentralized Application using Corda Distributed Ledger tutorial.

You should now be ready to develop your own CorDapps. If you want to learn more advance topics on Corda or other blockchain development platforms, the following classes are recommended:

Blockchain Hyperledger Fabric and Composer development- 30 hour course
Blockchain Ethereum development with Solidity- 30 hour course
Blockchain Corda R3 distributed ledger development- 30 hour course
Become Blockchain Certified Security Architect in 30 hours