mirror of
https://github.com/corda/corda.git
synced 2025-01-20 03:36:29 +00:00
Rewrite of docs on what a Cordapp is, how to write one, and how to build one.
This commit is contained in:
parent
617a941c83
commit
ee1e72d64c
@ -1,12 +1,13 @@
|
||||
Building a CorDapp
|
||||
==================
|
||||
CorDapps
|
||||
========
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
cordapp-overview
|
||||
writing-cordapps
|
||||
writing-a-cordapp
|
||||
cordapp-build-systems
|
||||
building-against-master
|
||||
api-index
|
||||
flow-cookbook
|
||||
cheat-sheet
|
@ -6,9 +6,9 @@ Corda nodes
|
||||
|
||||
deploying-a-node
|
||||
running-a-node
|
||||
corda-configuration-file
|
||||
clientrpc
|
||||
shell
|
||||
node-database
|
||||
node-administration
|
||||
corda-configuration-file
|
||||
out-of-process-verification
|
@ -1,47 +1,30 @@
|
||||
CorDapp Build Systems
|
||||
=====================
|
||||
Building a CorDapp
|
||||
==================
|
||||
|
||||
Cordapps run on the Corda platform and integrate with it and each other. To learn more about the basics of a Cordapp
|
||||
please read :doc:`cordapp-overview`. To learn about writing a Cordapp as a developer please read :doc:`writing-cordapps`.
|
||||
.. contents::
|
||||
|
||||
This article will specifically deal with how to build cordapps, specifically with Gradle.
|
||||
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 :doc:`cordapp-overview`.
|
||||
|
||||
CorDapp JAR format
|
||||
------------------
|
||||
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.
|
||||
|
||||
The first step to integrating a Cordapp with Corda is to ensure it is in the correct format. The correct format of a JAR
|
||||
is a semi-fat JAR that contains all of its own dependencies *except* the Corda core libraries and other Cordapps.
|
||||
For example, if a Cordapp depends on ``corda-core``, ``your-other-cordapp`` and ``apache-commons``, then the Cordapp
|
||||
JAR will contain:
|
||||
|
||||
For example if your 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 and *nothing* from the
|
||||
other two JARs.
|
||||
* All classes and resources from the ``apache-commons`` JAR and its dependencies
|
||||
* *Nothing* from the other two JARs
|
||||
|
||||
.. note:: The rest of this tutorial assumes you are using ``gradle``, the ``cordformation`` plugin and have forked from
|
||||
one of our cordapp templates.
|
||||
Build tools
|
||||
-----------
|
||||
In the instructions that follow, we assume you are using ``gradle`` and the ``cordformation`` plugin to build your
|
||||
CorDapp. See the `example build file <https://github.com/corda/cordapp-template-kotlin/blob/release-V1/build.gradle>`_
|
||||
from the CorDapp template.
|
||||
|
||||
The ``jar`` task included by default in the cordapp templates will automatically build your JAR in this format as long
|
||||
as your dependencies are correctly set.
|
||||
|
||||
The filename of the jar must include some sort of unique identifier to deduplicate it from other releases of the same
|
||||
CorDapp. This is typically done by appending the version string. It should not change once the jar has been deployed on
|
||||
a node. If it is then make sure no one is checking ``FlowContext.appName`` (see :doc:`versioning`).
|
||||
|
||||
Building against Corda
|
||||
----------------------
|
||||
|
||||
To build against Corda you must do the following to your ``build.gradle``;
|
||||
|
||||
* Add the ``net.corda:corda:<version>`` JAR as a ``cordaRuntime`` dependency.
|
||||
* Add each compile dependency (eg ``corda-core``) as a ``cordaCompile`` dependency.
|
||||
|
||||
To make use of the Corda test facilities you must;
|
||||
|
||||
* Add ``net.corda:corda-test-utils:<version>`` as a ``testCompile`` dependency (eg; a default Java/Kotlin compile task).
|
||||
|
||||
.. warning:: Never include ``corda-test-utils`` as a ``compile`` or ``cordaCompile`` dependency.
|
||||
|
||||
These configurations work by the ``cordformation`` plugin adding ``cordaCompile`` as a new configuration that ``compile``
|
||||
extends from, and ``cordaRuntime`` which ``runtime`` extends from.
|
||||
Setting your dependencies
|
||||
-------------------------
|
||||
|
||||
Choosing your Corda version
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
@ -49,11 +32,15 @@ The following two lines of the ``build.gradle`` file define the Corda version us
|
||||
|
||||
.. sourcecode:: groovy
|
||||
|
||||
ext.corda_release_version = '0.13.0'
|
||||
ext.corda_gradle_plugins_version = '0.13.3'
|
||||
ext.corda_release_version = '1.0.0'
|
||||
ext.corda_gradle_plugins_version = '1.0.0'
|
||||
|
||||
In this case, our CorDapp will use the Milestone 13 release of Corda, and version 13.3 of the Corda gradle plugins. You
|
||||
can find the latest published version of both here: https://bintray.com/r3/corda.
|
||||
In this case, our CorDapp will use:
|
||||
|
||||
* Version 1.0 of Corda
|
||||
* Version 1.0 of the Corda gradle plugins
|
||||
|
||||
You can find the latest published version of both here: https://bintray.com/r3/corda.
|
||||
|
||||
``corda_gradle_plugins_versions`` are given in the form ``major.minor.patch``. You should use the same ``major`` and
|
||||
``minor`` versions as the Corda version you are using, and the latest ``patch`` version. A list of all the available
|
||||
@ -61,34 +48,39 @@ versions can be found here: https://bintray.com/r3/corda/cordformation.
|
||||
|
||||
In certain cases, you may also wish to build against the unstable Master branch. See :doc:`building-against-master`.
|
||||
|
||||
Building against CorDapps
|
||||
-------------------------
|
||||
Corda dependencies
|
||||
^^^^^^^^^^^^^^^^^^
|
||||
The ``cordformation`` plugin adds:
|
||||
|
||||
To build against a Cordapp you must add it as a ``cordapp`` dependency to your ``build.gradle``.
|
||||
* ``cordaCompile`` as a new configuration that ``compile`` extends from
|
||||
* ``cordaRuntime`` which ``runtime`` extends from
|
||||
|
||||
Other Dependencies
|
||||
------------------
|
||||
To build against Corda you must add the following to your ``build.gradle`` file;
|
||||
|
||||
* The ``net.corda:corda:<version>`` JAR as a ``cordaRuntime`` dependency
|
||||
* Each compile dependency (eg ``corda-core``) as a ``cordaCompile`` dependency
|
||||
|
||||
To use Corda's test facilities you must add ``net.corda:corda-test-utils:<version>`` as a ``testCompile`` dependency
|
||||
(i.e. a default Java/Kotlin test compile task).
|
||||
|
||||
.. warning:: Never include ``corda-test-utils`` as a ``compile`` or ``cordaCompile`` dependency.
|
||||
|
||||
Dependencies on other CorDapps
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
Sometimes, a CorDapp you build will depend on states, contracts or flows defined in another CorDapp. You must include
|
||||
the CorDapp your CorDapp depends upon as a ``cordapp`` dependency in your ``build.gradle`` file.
|
||||
|
||||
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.
|
||||
|
||||
For further information about managing dependencies, see
|
||||
`the Gradle docs <https://docs.gradle.org/current/userguide/dependency_management.html>`_.
|
||||
|
||||
Installing CorDapps
|
||||
-------------------
|
||||
|
||||
At runtime, nodes will load any plugins present in their ``plugins`` folder. Therefore in order to install a cordapp to
|
||||
a node the cordapp JAR must be added to the ``<node_dir>/plugins/`` folder, where ``node_dir`` is the folder in which the
|
||||
node's JAR and configuration files are stored).
|
||||
|
||||
The ``deployNodes`` gradle task, if correctly configured, will automatically place your cordapp JAR as well as any
|
||||
dependent cordapp JARs specified into the directory automatically.
|
||||
|
||||
Example
|
||||
-------
|
||||
|
||||
The following is a sample of what a gradle dependencies block for a cordapp could look like. The cordapp template
|
||||
^^^^^^^
|
||||
The following is a sample of what a gradle dependencies block for a CorDapp could look like. The CorDapp template
|
||||
is already correctly configured and this is for reference only;
|
||||
|
||||
.. container:: codeset
|
||||
@ -108,6 +100,9 @@ is already correctly configured and this is for reference only;
|
||||
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
|
||||
@ -118,3 +113,29 @@ is already correctly configured and this is for reference only;
|
||||
compile "org.apache.commons:commons-lang3:3.6"
|
||||
}
|
||||
|
||||
Creating the CorDapp JAR
|
||||
------------------------
|
||||
The gradle ``jar`` task included in the CorDapp template build file will automatically build your CorDapp JAR correctly
|
||||
as long as your dependencies are set correctly.
|
||||
|
||||
Note that the hash of the resulting 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 (see :doc:`versioning`).
|
||||
|
||||
Installing the CorDapp jar
|
||||
--------------------------
|
||||
|
||||
.. note:: Before installing a CorDapp, you must create one or more nodes to install it on. For instructions, please see
|
||||
:doc:`deploying-a-node`.
|
||||
|
||||
At runtime, nodes will load any plugins present in their ``plugins`` folder. Therefore in order to install a CorDapp on
|
||||
a node, the CorDapp JAR must be added to the ``<node_dir>/plugins/`` folder, where ``node_dir`` is the folder in which
|
||||
the node's JAR and configuration files are stored.
|
||||
|
||||
The ``deployNodes`` gradle task, if correctly configured, will automatically place your CorDapp JAR as well as any
|
||||
dependent CorDapp JARs specified into the ``plugins`` folder automatically.
|
@ -1,25 +1,30 @@
|
||||
What is a CorDapp?
|
||||
==================
|
||||
|
||||
Corda is a platform. Its functionality is extended by developers through the writing of Corda distributed
|
||||
applications (CorDapps). CorDapps are installed at the level of the individual node, rather than on the network
|
||||
itself.
|
||||
|
||||
Each CorDapp allows a node to handle new business processes, for example asset trading (see :ref:`irs-demo`).
|
||||
It does so by defining new flows on the node that, once started by the node owner, conduct the process of negotiating
|
||||
a specific ledger update with other nodes on the network. The node's owner can then start these flows as required,
|
||||
either through remote procedure calls (RPC) or HTTP requests that leverage the RPC interface.
|
||||
CorDapps (Corda Distributed Applications) are distributed applications that run on the Corda platform. The goal of a
|
||||
CorDapp is to allow nodes to reach agreement on updates to the ledger. They achieve this goal by defining flows that
|
||||
Corda node owners can invoke through RPC calls:
|
||||
|
||||
.. image:: resources/node-diagram.png
|
||||
|
||||
CorDapp developers will usually define not only these flows, but also any states and contracts that these flows use.
|
||||
They will also have to define any web APIs that will run on the node's standalone web server, any static web content,
|
||||
and any new services that they want their CorDapp to offer.
|
||||
CorDapps are made up of the following key components:
|
||||
|
||||
CorDapps are made up of definitions for the following components:
|
||||
* States, defining the facts over which agreement is reached (see :doc:`Key Concepts - States <key-concepts-states>`)
|
||||
* Contracts, defining what constitutes a valid ledger update (see
|
||||
:doc:`Key Concepts - Contracts <key-concepts-contracts>`)
|
||||
* Services, providing long-lived utilities within the node
|
||||
* Serialisation whitelists, restricting what types your node will receive off the wire
|
||||
|
||||
* States
|
||||
* Contracts
|
||||
* Flows
|
||||
* Web APIs and static web content
|
||||
* Services
|
||||
Each CorDapp is installed at the level of the individual node, rather than on the network itself. For example, a node
|
||||
owner may choose to install the Bond Trading CorDapp, with the following components:
|
||||
|
||||
* A ``BondState``, used to represent bonds as shared facts on the ledger
|
||||
* A ``BondContract``, used to govern which ledger updates involving ``BondState`` states are valid
|
||||
* Three flows:
|
||||
|
||||
* An ``IssueBondFlow``, allowing new ``BondState`` states to be issued onto the ledger
|
||||
* A ``TradeBondFlow``, allowing existing ``BondState`` states to be bought and sold on the ledger
|
||||
* An ``ExitBondFlow``, allowing existing ``BondState`` states to be exited from the ledger
|
||||
|
||||
After installing this CorDapp, the node owner will be able to use the flows defined by the CorDapp to agree ledger
|
||||
updates related to issuance, sale, purchase and exit of bonds.
|
@ -1,97 +1,140 @@
|
||||
Deploying a node
|
||||
================
|
||||
|
||||
Using Gradle to build nodes
|
||||
---------------------------
|
||||
Nodes are usually built using a Gradle task. The canonical Gradle file for building nodes is the one used by the
|
||||
CorDapp template. Both a `Java version <https://github.com/corda/cordapp-template-java/blob/master/build.gradle>`_ and
|
||||
a `Kotlin version <https://github.com/corda/cordapp-template-kotlin/blob/master/build.gradle>`_ are available.
|
||||
Node structure
|
||||
--------------
|
||||
Each Corda node has the following structure:
|
||||
|
||||
Cordform is the local node deployment system for CorDapps. The nodes generated are intended for experimenting,
|
||||
debugging, and testing node configurations, but not for production or testnet deployment.
|
||||
.. sourcecode:: none
|
||||
|
||||
Here is an example Gradle task called ``deployNodes`` that uses the Cordform plugin to deploy three nodes, plus a
|
||||
notary/network map node:
|
||||
.
|
||||
├── certificates // The node's doorman certificates
|
||||
├── corda-webserver.jar // The built-in node webserver
|
||||
├── corda.jar // The core Corda libraries
|
||||
├── logs // The node logs
|
||||
├── node.conf // The node's configuration files
|
||||
├── persistence.mv.db // The node's database
|
||||
└── plugins // The CorDapps jars installed on the node
|
||||
|
||||
The node is configured by editing its ``node.conf`` file. You install CorDapps on the node by dropping the CorDapp JARs
|
||||
into the ``plugins`` folder.
|
||||
|
||||
Node naming
|
||||
-----------
|
||||
A node's name must be a valid X500 name that obeys the following additional constraints:
|
||||
|
||||
* The fields of the name have the following maximum character lengths:
|
||||
|
||||
* Common name: 64
|
||||
* Organisation: 128
|
||||
* Organisation unit: 64
|
||||
* Locality: 64
|
||||
* State: 64
|
||||
|
||||
* The country code is a valid ISO 3166-1 two letter code in upper-case
|
||||
|
||||
* The organisation, locality and country attributes are present
|
||||
|
||||
* The organisation field of the name obeys the following constraints:
|
||||
|
||||
* Has at least two letters
|
||||
* No leading or trailing whitespace
|
||||
* No double-spacing
|
||||
* Upper-case first letter
|
||||
* Does not contain the words "node" or "server"
|
||||
* Does not include the characters ',' or '=' or '$' or '"' or '\'' or '\\'
|
||||
* Is in NFKC normalization form
|
||||
* Only the latin, common and inherited unicode scripts are supported
|
||||
|
||||
The deployNodes task
|
||||
--------------------
|
||||
The CorDapp template defines a ``deployNodes`` task that allows you to automatically generate and configure a set of
|
||||
nodes:
|
||||
|
||||
.. sourcecode:: groovy
|
||||
|
||||
task deployNodes(type: net.corda.plugins.Cordform, dependsOn: ['jar']) {
|
||||
directory "./build/nodes"
|
||||
networkMap "O=Controller,OU=corda,L=London,C=UK"
|
||||
networkMap "O=Controller,L=London,C=GB"
|
||||
node {
|
||||
name "O=Controller,OU=corda,L=London,C=UK"
|
||||
name "O=Controller,L=London,C=GB"
|
||||
// The notary will offer a validating notary service.
|
||||
// Set to `corda.notary.simple` for a non-validating notary.
|
||||
advertisedServices = ["corda.notary.validating"]
|
||||
p2pPort 10002
|
||||
rpcPort 10003
|
||||
webPort 10004
|
||||
cordapps = []
|
||||
p2pPort 10002
|
||||
rpcPort 10003
|
||||
// No webport property, so no webserver will be created.
|
||||
h2Port 10004
|
||||
sshdPort 22
|
||||
// Includes the corda-finance CorDapp on our node.
|
||||
cordapps = ["net.corda:corda-finance:$corda_release_version"]
|
||||
}
|
||||
node {
|
||||
name "CN=NodeA,O=NodeA,L=London,C=UK"
|
||||
name "O=PartyA,L=London,C=GB"
|
||||
advertisedServices = []
|
||||
p2pPort 10005
|
||||
rpcPort 10006
|
||||
webPort 10007
|
||||
cordapps = []
|
||||
rpcUsers = [[ user: "user1", "password": "test", "permissions": []]]
|
||||
p2pPort 10005
|
||||
rpcPort 10006
|
||||
webPort 10007
|
||||
h2Port 10008
|
||||
sshdPort 22
|
||||
cordapps = ["net.corda:corda-finance:$corda_release_version"]
|
||||
// Grants user1 all RPC permissions.
|
||||
rpcUsers = [[ user: "user1", "password": "test", "permissions": ["ALL"]]]
|
||||
}
|
||||
node {
|
||||
name "CN=NodeB,O=NodeB,L=New York,C=US"
|
||||
name "O=PartyB,L=New York,C=US"
|
||||
advertisedServices = []
|
||||
p2pPort 10008
|
||||
rpcPort 10009
|
||||
webPort 10010
|
||||
cordapps = []
|
||||
rpcUsers = [[ user: "user1", "password": "test", "permissions": []]]
|
||||
}
|
||||
node {
|
||||
name "CN=NodeC,O=NodeC,L=Paris,C=FR"
|
||||
advertisedServices = []
|
||||
p2pPort 10011
|
||||
rpcPort 10012
|
||||
webPort 10013
|
||||
cordapps = []
|
||||
rpcUsers = [[ user: "user1", "password": "test", "permissions": []]]
|
||||
p2pPort 10009
|
||||
rpcPort 10010
|
||||
webPort 10011
|
||||
h2Port 10012
|
||||
sshdPort 22
|
||||
cordapps = ["net.corda:corda-finance:$corda_release_version"]
|
||||
// Grants user1 the ability to start the MyFlow flow.
|
||||
rpcUsers = [[ user: "user1", "password": "test", "permissions": ["StartFlow.net.corda.flows.MyFlow"]]]
|
||||
}
|
||||
}
|
||||
|
||||
You can extend ``deployNodes`` to generate any number of nodes you like. The only requirement is that you must specify
|
||||
one node as running the network map service, by putting their name in the ``networkMap`` field. In our example, the
|
||||
``Controller`` is set as the network map service.
|
||||
Running this task will create three nodes in the ``build/nodes`` folder:
|
||||
|
||||
* A ``Controller`` node that:
|
||||
|
||||
* Serves as the network map
|
||||
* Offers a validating notary service
|
||||
* Will not have a webserver (since ``webPort`` is not defined)
|
||||
* Is running the ``corda-finance`` CorDapp
|
||||
|
||||
* ``PartyA`` and ``PartyB`` nodes that:
|
||||
|
||||
* Are pointing at the ``Controller`` as the network map service
|
||||
* Are not offering any services
|
||||
* Will have a webserver (since ``webPort`` is defined)
|
||||
* Are running the ``corda-finance`` CorDapp
|
||||
* Have an RPC user, ``user1``, that can be used to log into the node via RPC
|
||||
|
||||
Additionally, all three nodes will include any CorDapps defined in the project's source folders, even though these
|
||||
CorDapps are not listed in each node's ``cordapps`` entry. This means that running the ``deployNodes`` task from the
|
||||
template CorDapp, for example, would automatically build and add the template CorDapp to each node.
|
||||
|
||||
You can extend ``deployNodes`` to generate additional nodes. The only requirement is that you must specify
|
||||
a single node to run the network map service, by putting their name in the ``networkMap`` field.
|
||||
|
||||
.. warning:: When adding nodes, make sure that there are no port clashes!
|
||||
|
||||
If your CorDapp is written in Java, you should also add the following Gradle snippet so that you can pass named arguments to your flows via the Corda shell:
|
||||
|
||||
.. sourcecode:: groovy
|
||||
|
||||
tasks.withType(JavaCompile) {
|
||||
options.compilerArgs << "-parameters"
|
||||
}
|
||||
|
||||
Any CorDapps defined in the project's source folders are also automatically registered with all the nodes defined in
|
||||
``deployNodes``, even if the CorDapps are not listed in each node's ``cordapps`` entry.
|
||||
|
||||
Deploying your nodes
|
||||
--------------------
|
||||
You deploy a set of nodes by running your ``build.gradle`` file's Cordform task. For example, if we were using the
|
||||
standard ``deployNodes`` task defined above, we'd create our nodes by running the following commands in a terminal
|
||||
window from the root of the project:
|
||||
Running deployNodes
|
||||
-------------------
|
||||
To create the nodes defined in our ``deployNodes`` task, we'd run the following command in a terminal window from the
|
||||
root of the project:
|
||||
|
||||
* Unix/Mac OSX: ``./gradlew deployNodes``
|
||||
* Windows: ``gradlew.bat deployNodes``
|
||||
|
||||
After the build process has finished, you will find the newly-built nodes under ``kotlin-source/build/nodes``. There
|
||||
will be one folder generated for each node you built, plus a ``runnodes`` shell script (or batch file on Windows) to
|
||||
run all the nodes at once. Each node in the ``nodes`` folder has the following structure:
|
||||
This will create the nodes in the ``build/nodes`` folder.
|
||||
|
||||
.. sourcecode:: none
|
||||
.. warning:: Outside of development environments, do not store your node directories in the build folder.
|
||||
|
||||
. nodeName
|
||||
├── corda.jar // The Corda runtime
|
||||
├── node.conf // The node's configuration
|
||||
└── plugins // Any installed CorDapps
|
||||
There will be a node folder generated for each node you defined, plus a ``runnodes`` shell script (or batch file on
|
||||
Windows) to run all the nodes at once. If you make any changes to your ``deployNodes`` task, you will need to re-run
|
||||
the task to see the changes take effect.
|
||||
|
||||
.. note:: Outside of development environments, do not store your node directories in the build folder.
|
||||
|
||||
If you make any changes to your ``deployNodes`` task, you will need to re-run the task to see the changes take effect.
|
||||
You can now run the nodes by following the instructions in :doc:`Running a node <running-a-node>`.
|
@ -7,5 +7,4 @@ Quickstart
|
||||
getting-set-up
|
||||
tutorial-cordapp
|
||||
Sample CorDapps <https://www.corda.net/samples/>
|
||||
building-against-master
|
||||
CLI-vs-IDE
|
@ -23,7 +23,6 @@ Classes get onto the whitelist via one of three mechanisms:
|
||||
class itself, on any of the super classes or on any interface implemented by the class or super classes or any
|
||||
interface extended by an interface implemented by the class or superclasses.
|
||||
#. By implementing the ``SerializationWhitelist`` interface and specifying a list of `whitelist` classes.
|
||||
See :doc:`writing-cordapps`.
|
||||
#. Via the built in Corda whitelist (see the class ``DefaultWhitelist``). Whilst this is not user editable, it does list
|
||||
common JDK classes that have been whitelisted for your convenience.
|
||||
|
||||
|
146
docs/source/writing-a-cordapp.rst
Normal file
146
docs/source/writing-a-cordapp.rst
Normal file
@ -0,0 +1,146 @@
|
||||
Writing a CorDapp
|
||||
=================
|
||||
|
||||
.. contents::
|
||||
|
||||
Overview
|
||||
--------
|
||||
CorDapps can be written in either Java, Kotlin, or a combination of the two. Each CorDapp component takes the form
|
||||
of a JVM class that subclasses or implements a Corda library type:
|
||||
|
||||
* Flows subclass ``FlowLogic``
|
||||
* States implement ``ContractState``
|
||||
* Contracts implement ``Contract``
|
||||
* Services subclass ``SingletonSerializationToken``
|
||||
* Serialisation whitelists implement ``SerializationWhitelist``
|
||||
|
||||
Web content and RPC clients
|
||||
---------------------------
|
||||
For testing purposes, CorDapps may also include:
|
||||
|
||||
* **APIs and static web content**: These are served by Corda's built-in webserver. This webserver is not
|
||||
production-ready, and should be used for testing purposes only
|
||||
|
||||
* **RPC clients**: These are programs that automate the process of interacting with a node via RPC
|
||||
|
||||
In production, a production-ready webserver should be used, and these files should be moved into a different module or
|
||||
project so that they do not bloat the CorDapp at build time.
|
||||
|
||||
Structure
|
||||
---------
|
||||
You should base the structure of your project on the Java or Kotlin templates:
|
||||
|
||||
* `Java Template CorDapp <https://github.com/corda/cordapp-template-java>`_
|
||||
* `Kotlin Template CorDapp <https://github.com/corda/cordapp-template-kotlin>`_
|
||||
|
||||
The project should be split into two modules:
|
||||
|
||||
* A ``cordapp-contracts-states`` module containing classes such as contracts and states that will be sent across the
|
||||
wire as part of a flow
|
||||
* A ``cordapp`` module containing the remaining classes
|
||||
|
||||
Each module will be compiled into its own CorDapp. This minimises the size of the JAR that has to be sent across the
|
||||
wire when nodes are agreeing ledger updates.
|
||||
|
||||
Module one - cordapp-contracts-states
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
Here is the structure of the ``src`` directory for the ``cordapp-contracts-states`` module:
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
.
|
||||
└── 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:
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
.
|
||||
├── 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:
|
||||
|
||||
* ``resources/META-INF/services`` contains registries of the CorDapp's serialisation whitelists and web plugins
|
||||
* ``resources/certificates`` contains dummy certificates for test purposes
|
||||
* ``resources/templateWeb`` contains a dummy front-end
|
||||
* ``java`` (or ``kotlin`` in the Kotlin template), which includes the source-code for our CorDapp
|
||||
|
||||
The source-code for our CorDapp breaks down as follows:
|
||||
|
||||
* ``TemplateFlow.java``, which contains a dummy ``FlowLogic`` subclass
|
||||
* ``TemplateState.java``, which contains a dummy ``ContractState`` implementation
|
||||
* ``TemplateContract.java``, which contains a dummy ``Contract`` implementation
|
||||
* ``TemplateSerializationWhitelist.java``, which contains a dummy ``SerializationWhitelist`` implementation
|
||||
|
||||
In developing your CorDapp, you should start by modifying these classes to define the components of your CorDapp. A
|
||||
single CorDapp can define multiple flows, states, and contracts.
|
||||
|
||||
The template also includes a web API and RPC client:
|
||||
|
||||
* ``TemplateApi.java``
|
||||
* ``TemplateClient.java``
|
||||
* ``TemplateWebPlugin.java``
|
||||
|
||||
These are for testing purposes and would be removed in a production CorDapp.
|
||||
|
||||
Resources
|
||||
---------
|
||||
In writing a CorDapp, you should consult the following resources:
|
||||
|
||||
* :doc:`Getting Set Up </getting-set-up>` to set up your development environment
|
||||
* The :doc:`Hello, World! tutorial </hello-world-index>` to write your first CorDapp
|
||||
* :doc:`Building a CorDapp </cordapp-build-systems>` to build and run your CorDapp
|
||||
* The :doc:`API docs </api-index>` to read about the API available in developing CorDapps
|
||||
|
||||
* There is also a :doc:`cheatsheet </cheat-sheet>` recapping the key types
|
||||
|
||||
* The :doc:`Flow cookbook </flow-cookbook>` to see code examples of how to perform common flow tasks
|
||||
* `Sample CorDapps <https://www.corda.net/samples/>`_ showing various parts of Corda's functionality
|
@ -1,61 +0,0 @@
|
||||
Writing a CorDapp
|
||||
=================
|
||||
|
||||
When writing a CorDapp, you are writing a set of files in a JVM language that defines one or more of the following
|
||||
Corda components:
|
||||
|
||||
* States (i.e. classes implementing ``ContractState``)
|
||||
* Contracts (i.e. classes implementing ``Contract``)
|
||||
* Flows (i.e. classes extending ``FlowLogic``)
|
||||
* Web APIs
|
||||
* Services
|
||||
|
||||
CorDapp structure
|
||||
-----------------
|
||||
Your CorDapp project's structure should be based on the structure of the
|
||||
`Java Template CorDapp <https://github.com/corda/cordapp-template-java>`_ or the
|
||||
`Kotlin Template CorDapp <https://github.com/corda/cordapp-template-kotlin>`_, depending on which language you intend
|
||||
to use.
|
||||
|
||||
The ``src`` directory of the Template CorDapp, where we define our CorDapp's source-code, has the following structure:
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
src
|
||||
├── main
|
||||
│ ├── java
|
||||
│ │ └── com
|
||||
│ │ └── template
|
||||
│ │ ├── Main.java
|
||||
│ │ ├── api
|
||||
│ │ │ └── TemplateApi.java
|
||||
│ │ ├── client
|
||||
│ │ │ └── TemplateClientRPC.java
|
||||
│ │ ├── contract
|
||||
│ │ │ └── TemplateContract.java
|
||||
│ │ ├── flow
|
||||
│ │ │ └── TemplateFlow.java
|
||||
│ │ ├── plugin
|
||||
│ │ │ └── TemplatePlugin.java
|
||||
│ │ ├── service
|
||||
│ │ │ └── TemplateService.java
|
||||
│ │ └── state
|
||||
│ │ └── TemplateState.java
|
||||
│ └── resources
|
||||
│ ├── META-INF
|
||||
│ │ └── services
|
||||
│ │ ├── net.corda.core.serialization.SerializationWhitelist
|
||||
│ │ └── net.corda.webserver.services.WebServerPluginRegistry
|
||||
│ ├── certificates
|
||||
│ │ ├── sslkeystore.jks
|
||||
│ │ └── truststore.jks
|
||||
│ └──templateWeb
|
||||
│ ├── index.html
|
||||
│ └── js
|
||||
│ └── template-js.js
|
||||
└── test
|
||||
└── java
|
||||
└── com
|
||||
└── template
|
||||
└── contract
|
||||
└── TemplateTests.java
|
Loading…
Reference in New Issue
Block a user