From bb4501c09cc6979c2076ac4a3e9f04d138af5dcd Mon Sep 17 00:00:00 2001 From: Joel Dudley Date: Fri, 21 Jul 2017 12:33:31 +0100 Subject: [PATCH] Updates the example CorDapp page. --- docs/source/building-against-master.rst | 34 + docs/source/corda-nodes-index.rst | 2 + docs/source/deploying-a-node.rst | 125 +++ docs/source/getting-set-up.rst | 9 +- docs/source/node-database.rst | 28 + docs/source/quickstart-index.rst | 1 + docs/source/running-a-node.rst | 168 +--- docs/source/tutorial-cordapp.rst | 1121 +++++++++-------------- 8 files changed, 624 insertions(+), 864 deletions(-) create mode 100644 docs/source/building-against-master.rst create mode 100644 docs/source/deploying-a-node.rst create mode 100644 docs/source/node-database.rst diff --git a/docs/source/building-against-master.rst b/docs/source/building-against-master.rst new file mode 100644 index 0000000000..af3d87e25d --- /dev/null +++ b/docs/source/building-against-master.rst @@ -0,0 +1,34 @@ +Building against Master +======================= + +When developing a CorDapp, it is advisable to use the most recent Corda Milestone release, which has been extensively +tested. However, if you need to use a very recent feature of the codebase, you may need to work against the unstable +Master branch. + +To work against the Master branch, proceed as follows: + +* Open a terminal window in the folder where you cloned the Corda repository + (available `here `_) + +* Use the following command to check out the latest master branch: + + ``git fetch; git checkout master`` + +* Publish Corda to your local Maven repository using the following commands: + + * Unix/Mac OSX: ``./gradlew install`` + * Windows: ``gradlew.bat install`` + + By default, the Maven local repository is found at: + + * ``~/.m2/repository`` on Unix/Mac OS X + * ``%HOMEPATH%\.m2`` on Windows + + This step is not necessary when using a Milestone releases, as the Milestone releases are published online + +.. warning:: If you do modify your local Corda repository after having published it to Maven local, then you must + re-publish it to Maven local for the local installation to reflect the changes you have made. + +.. warning:: As the Corda repository evolves on a daily basis, two clones of the Master branch at different points in + time may differ. If you are using a Master release and need help debugging an error, then please let us know the + **commit** you are working from. This will help us ascertain the issue. \ No newline at end of file diff --git a/docs/source/corda-nodes-index.rst b/docs/source/corda-nodes-index.rst index 0297f1c744..6389d7c23b 100644 --- a/docs/source/corda-nodes-index.rst +++ b/docs/source/corda-nodes-index.rst @@ -4,9 +4,11 @@ Corda nodes .. toctree:: :maxdepth: 1 + deploying-a-node running-a-node clientrpc shell + node-database node-administration corda-configuration-file out-of-process-verification \ No newline at end of file diff --git a/docs/source/deploying-a-node.rst b/docs/source/deploying-a-node.rst new file mode 100644 index 0000000000..d7ca6e2804 --- /dev/null +++ b/docs/source/deploying-a-node.rst @@ -0,0 +1,125 @@ +Deploying a node +================ + +Building nodes using Gradle +--------------------------- +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 `_ and +a `Kotlin version `_ are available. + +The buildscript +~~~~~~~~~~~~~~~ +The buildscript is always located at the top of the build file. Among other things, this section determines which +version of Corda and the Corda gradle plugins are used to build the nodes and their CorDapps: + +.. sourcecode:: groovy + + ext.corda_release_version = '0.14-SNAPSHOT' + ext.corda_gradle_plugins_version = '0.14.2' + +Release versions suffixed by ``-SNAPSHOT`` are based on the unstable Master branch +(see :doc:`building-against-master`). You should generally use the latest Milestone release instead. + +``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 +versions can be found here: https://bintray.com/r3/corda/cordformation. + +Project dependencies +~~~~~~~~~~~~~~~~~~~~ +If your CorDapps have any additional external dependencies, they should be added to the ``dependencies`` section:` + +.. sourcecode:: groovy + + dependencies { + + ... + + // Cordapp dependencies + // Specify your cordapp's dependencies below, including dependent cordapps + } + +For further information about managing dependencies, see +`the Gradle docs `_. + +Building the nodes +~~~~~~~~~~~~~~~~~~ +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. + +Here is an example Gradle task called ``deployNodes`` that uses the Cordform plugin to deploy three nodes, plus a +notary/network map node: + +.. sourcecode:: groovy + + task deployNodes(type: net.corda.plugins.Cordform, dependsOn: ['jar']) { + directory "./build/nodes" + networkMap "CN=Controller,O=R3,OU=corda,L=London,C=UK" + node { + name "CN=Controller,O=R3,OU=corda,L=London,C=UK" + advertisedServices = ["corda.notary.validating"] + p2pPort 10002 + rpcPort 10003 + webPort 10004 + cordapps = [] + } + node { + name "CN=NodeA,O=NodeA,L=London,C=UK" + advertisedServices = [] + p2pPort 10005 + rpcPort 10006 + webPort 10007 + cordapps = [] + rpcUsers = [[ user: "user1", "password": "test", "permissions": []]] + } + node { + name "CN=NodeB,O=NodeB,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": []]] + } + } + +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. + +.. warning:: When adding nodes, make sure that there are no port clashes! + +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: + +* 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: + +.. sourcecode:: none + + . nodeName + ├── corda.jar // The Corda runtime + ├── node.conf // The node's configuration + └── plugins // Any installed CorDapps + +.. 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. \ No newline at end of file diff --git a/docs/source/getting-set-up.rst b/docs/source/getting-set-up.rst index ac221d2217..0dd81242e3 100644 --- a/docs/source/getting-set-up.rst +++ b/docs/source/getting-set-up.rst @@ -158,11 +158,14 @@ instead by running ``git checkout release-M12``. Next steps ---------- +The best way to check that everything is working fine is by running the :doc:`tutorial CorDapp ` and +the :doc:`samples `. -The best way to check that everything is working fine is by :doc:`running-the-demos`. +Next, you should read through :doc:`Corda Key Concepts ` to understand how Corda works. -Once you have these demos running, you may be interested in writing your own CorDapps, in which case you should refer to -:doc:`tutorial-cordapp`. +By then, you'll be ready to start writing your own CorDapps. Learn how to do this in the +:doc:`Hello, World tutorial `. You may want to refer to the :doc:`API docs ` along the +way. If you encounter any issues, please see the :doc:`troubleshooting` page, or get in touch with us on the `forums `_ or via `slack `_. diff --git a/docs/source/node-database.rst b/docs/source/node-database.rst new file mode 100644 index 0000000000..e38cde81c9 --- /dev/null +++ b/docs/source/node-database.rst @@ -0,0 +1,28 @@ +Node database +============= + +Currently, nodes store their data in an H2 database. In the future, we plan to support a wide range of databases. + +You can connect directly to a running node's database to see its stored states, transactions and attachments as +follows: + +* Download the `h2 platform-independent zip `_, unzip the zip, and + navigate in a terminal window to the unzipped folder +* Change directories to the bin folder: + + ``cd h2/bin`` + +* Run the following command to open the h2 web console in a web browser tab: + + * Unix: ``sh h2.sh`` + * Windows: ``h2.bat`` + +* Find the node's JDBC connection string. Each node outputs its connection string in the terminal + window as it starts up. In a terminal window where a node is running, look for the following string: + + ``Database connection URL is : jdbc:h2:tcp://10.18.0.150:56736/node`` + +* Paste this string into the JDBC URL field and click ``Connect``, using the default username and password. + +You will be presented with a web interface that shows the contents of your node's storage and vault, and provides an +interface for you to query them using SQL. \ No newline at end of file diff --git a/docs/source/quickstart-index.rst b/docs/source/quickstart-index.rst index 12404a0d8f..59f6042658 100644 --- a/docs/source/quickstart-index.rst +++ b/docs/source/quickstart-index.rst @@ -7,4 +7,5 @@ Quickstart getting-set-up tutorial-cordapp running-the-demos + building-against-master CLI-vs-IDE \ No newline at end of file diff --git a/docs/source/running-a-node.rst b/docs/source/running-a-node.rst index 9ec08fdc73..ec03aa80bd 100644 --- a/docs/source/running-a-node.rst +++ b/docs/source/running-a-node.rst @@ -1,38 +1,20 @@ Running a node ============== -Deploying your node -------------------- - -You deploy a node by running the ``gradle deployNodes`` task. This will output the node JAR to -``build/libs/corda.jar`` and several sample/standard node setups to ``build/nodes``. For now you can use the -``build/nodes/nodea`` configuration as a template. - -Each node server by default must have a ``node.conf`` file in the current working directory. After first -execution of the node server there will be many other configuration and persistence files created in this -workspace directory. The directory can be overridden by the ``--base-directory=`` command line argument. - -.. note:: Outside of development environments do not store your node directories in the build folder. - -.. warning:: Also note that the bootstrapping process of the ``corda.jar`` unpacks the Corda dependencies into a - temporary folder. It is therefore suggested that the CAPSULE_CACHE_DIR environment variable be set before - starting the process to control this location. - Starting your node ------------------ -Now you have a node server with your app installed, you can run it by navigating to ```` and running: +After following the steps in :doc:`deploying-a-node`, you should have deployed your node(s) with any chosen CorDapps +installed. You run each node by navigating to ```` in a terminal window and running: .. code-block:: shell Windows: java -jar corda.jar UNIX: ./corda.jar -The plugin should automatically be registered and the configuration file used. - .. warning:: If your working directory is not ```` your plugins and configuration will not be used. -The configuration file and workspace paths can be overidden on the command line e.g. +The configuration file and workspace paths can be overridden on the command line. For example: ``./corda.jar --config-file=test.conf --base-directory=/opt/r3corda/nodes/test``. @@ -41,14 +23,14 @@ Otherwise the workspace folder for the node is the current working path. Debugging your node ------------------- -To enable remote debugging of the corda process use a command line such as: +To enable remote debugging of the node, run the following from the terminal window: ``java -Dcapsule.jvm.args="-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=5005" -jar corda.jar`` This command line will start the debugger on port 5005 and pause the process awaiting debugger attachment. -Viewing persisted state of your node ------------------------------------- +Viewing the persisted state of your node +---------------------------------------- To make examining the persisted contract states of your node or the internal node database tables easier, and providing you are using the default database configuration used for demos, you should be able to connect to the internal node database over @@ -61,140 +43,4 @@ at the present time, and should certainly be treated as read-only. .. _CordaPluginRegistry: api/kotlin/corda/net.corda.core.node/-corda-plugin-registry/index.html .. _PluginServiceHub: api/kotlin/corda/net.corda.core.node/-plugin-service-hub/index.html -.. _ServiceHub: api/kotlin/corda/net.corda.core.node/-service-hub/index.html - -Building against Corda ----------------------- - -To publish to your local Maven repository (in ``~/.m2`` on Unix and ``%HOMEPATH%\.m2`` on Windows) run the following -in the root directory of the Corda code: - -.. code-block:: shell - - ./gradlew install - -This will publish corda-$version.jar, finance-$version.jar, core-$version.jar and node-$version.jar to the -group net.corda. You can now depend on these as you normally would a Maven dependency, using the group id -``net.corda``. - -There are several Gradle plugins that reduce your build.gradle boilerplate and make development of CorDapps easier. -The available plugins are in the gradle-plugins directory of the Corda repository. - -To install to your local Maven repository the plugins that CorDapp gradle files require, enter the ``gradle-plugins`` -directory and then run ``../gradle install``. The plugins will now be installed to your local Maven repository. - -Using Gradle plugins -~~~~~~~~~~~~~~~~~~~~ - -To use the plugins, if you are not already using the CorDapp template project, you must modify your build.gradle. Add -the following segments to the relevant part of your build.gradle. - -.. code-block:: groovy - - buildscript { - ext.corda_release_version = '' - ext.corda_gradle_plugins_version = '' // This is usually the same as corda_release_version. - ... your buildscript ... - - repositories { - ... other repositories ... - mavenLocal() - } - - dependencies { - ... your dependencies ... - classpath "net.corda.plugins:cordformation:$corda_gradle_plugins_version" - classpath "net.corda.plugins:quasar-utils:$corda_gradle_plugins_version" - classpath "net.corda.plugins:publish-utils:$corda_gradle_plugins_version" - } - } - - apply plugin: 'net.corda.plugins.cordformation' - apply plugin: 'net.corda.plugins.quasar-utils' - apply plugin: 'net.corda.plugins.publish-utils' - - repositories { - mavenLocal() - ... other repositories here ... - } - - dependencies { - compile "net.corda.core:$corda_release_version" - compile "net.corda.finance:$corda_release_version" - compile "net.corda.node:$corda_release_version" - compile "net.corda.corda:$corda_release_version" - ... other dependencies here ... - } - - ... your tasks ... - - // Standard way to publish CorDapps to maven local with the maven-publish and publish-utils plugin. - publishing { - publications { - jarAndSources(MavenPublication) { - from components.java - // The two lines below are the tasks added by this plugin. - artifact sourceJar - artifact javadocJar - } - } - } - - - -Cordformation -~~~~~~~~~~~~~ - -Cordformation is the local node deployment system for CorDapps, the nodes generated are intended to be used for -experimenting, debugging, and testing node configurations and setups but not intended for production or testnet -deployment. - -To use this gradle plugin you must add a new task that is of the type ``net.corda.plugins.Cordform`` to your -build.gradle and then configure the nodes you wish to deploy with the Node and nodes configuration DSL. -This DSL is specified in the `JavaDoc `_. An example of this is in the CorDapp template and -below -is a three node example; - -.. code-block:: text - - task deployNodes(type: net.corda.plugins.Cordform, dependsOn: ['jar']) { - directory "./build/nodes" // The output directory - networkMap "CN=Controller,O=R3,OU=corda,L=London,C=GB" // The distinguished name of the node named here will be used as the networkMapService.address on all other nodes. - node { - name "CN=Controller,O=R3,OU=corda,L=London,C=GB" - advertisedServices = [ "corda.notary.validating" ] - p2pPort 10002 - rpcPort 10003 - webPort 10004 - h2Port 11002 - cordapps [] - } - node { - name "CN=NodeA,O=R3,OU=corda,L=London,C=GB" - advertisedServices = [] - p2pPort 10005 - rpcPort 10006 - webPort 10007 - h2Port 11005 - cordapps [] - } - node { - name "CN=NodeB,O=R3,OU=corda,L=New York,C=US" - advertisedServices = [] - p2pPort 10008 - rpcPort 10009 - webPort 10010 - h2Port 11008 - cordapps [] - } - } - -You can create more configurations with new tasks that extend Cordform. - -New nodes can be added by simply adding another node block and giving it a different name, directory and ports. When you -run this task it will install the nodes to the directory specified and a script will be generated to run the nodes with -one command (``runnodes``). On MacOS X this script will run each node in a new terminal tab, and on Linux it will open -up a new XTerm for each node. On Windows the (``runnodes.bat``) script will run one node per window. - -Other CorDapps can also be specified if they are already specified as classpath or compile dependencies in your -``build.gradle``. +.. _ServiceHub: api/kotlin/corda/net.corda.core.node/-service-hub/index.html \ No newline at end of file diff --git a/docs/source/tutorial-cordapp.rst b/docs/source/tutorial-cordapp.rst index c17c81b874..350c0a63c4 100644 --- a/docs/source/tutorial-cordapp.rst +++ b/docs/source/tutorial-cordapp.rst @@ -7,832 +7,549 @@ The example CorDapp =================== -This guide covers how to get started with the example CorDapp. Please note there are several Corda repositories: +.. contents:: -* `corda `_ which contains the core platform code and sample CorDapps. -* `cordapp-tutorial `_ which contains an example CorDapp you can use to bootstrap your own CorDapps. It is the subject of this tutorial and should help you understand the basics. -* `cordapp-template `_ which contains a bare-bones template designed for starting new projects by copying. +The example CorDapp allows nodes to agree IOUs with each other. Nodes will always agree to the creation of a new IOU +unless: -We recommend you read the non-technical white paper and technical white paper before you get started with Corda: +* Its value is less than 1, or greater than 99 +* A node tries to issue an IOU to itself -1. `The Introductory white paper `_ describes the - motivating vision and background of the project. It is the kind of document your boss should read. It describes why the - project exists and briefly compares it to alternative systems on the market. -2. `The Technical white paper `_ describes the entire - intended design from beginning to end. It is the kind of document that you should read, or at least, read parts of. Note - that because the technical white paper describes the intended end state, it does not always align with the implementation. - -Background ----------- - -The example CorDapp implements a basic scenario where one party wishes to send an IOU to another party. The scenario -defines four nodes: +By default, the CorDapp is deployed on 4 test nodes: * **Controller**, which hosts the network map service and validating notary service * **NodeA** * **NodeB** * **NodeC** -The nodes can generate IOUs and send them to other nodes. The flows used to facilitate the agreement process always results in -an agreement with the recipient as long as the IOU meets the contract constraints which are defined in ``IOUContract.kt``. +Because data is only propagated on a need-to-know basis, any IOUs agreed between NodeA and NodeB become "shared facts" +between NodeA and NodeB only. NodeC won't be aware of these IOUs. -All agreed IOUs between NodeA and NodeB become "shared facts" between NodeA and NodeB. But note that NodeC -won't see any of these transactions or have copies of any of the resulting ``IOUState`` objects. This is -because data is only propagated on a need-to-know basis. - -Getting started ---------------- - -There are two ways to get started with the example CorDapp. You can either work from a milestone release of Corda or a -SNAPSHOT release of Corda. - -**Using a monthly Corda milestone release.** If you wish to develop your CorDapp using the most recent milestone release -then you can get started simply by cloning the ``cordapp-tutorial`` repository. Gradle will grab all the required dependencies -for you from our `public Maven repository `_. - -**Using a Corda SNAPSHOT build.** Alternatively, if you wish to work from the master branch of the Corda repo which contains -the most up-to-date Corda feature set then you will need to clone the ``corda`` repository and publish the latest master -build (or previously tagged releases) to your local Maven repository. You will then need to ensure that Gradle -grabs the correct dependencies for you from Maven local by changing the ``corda_release_version`` in ``build.gradle``. -This will be covered below in `Using a SNAPSHOT release`_. - -Firstly, follow the :doc:`getting set up ` page to download the JDK, IntelliJ and git if you didn't -already have it. - -Working from milestone releases -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -If you wish to build a CorDapp against a milestone release then please use these instructions. - -The process for developing your CorDapp from a milestone release is the most simple way to get started and is the preferred -approach. - -We publish all our milestone releases to a public Maven repository on a monthly basis. As such, Gradle will automatically -grab the appropriately versioned (specified in the ``cordapp-tutorial``'s ``build.gradle`` file) dependencies for you from Maven. -All you have to do is check out the release tag of the tutorial version you wish to use. - -By default, the ``master`` branch of the ``cordapp-tutorial`` points to a SNAPSHOT release of Corda, this is because it is -being constantly updated to reflect the changes in the master branch of the `corda` repository. - -.. note:: If you wish to use a SNAPSHOT release then follow the instructions below: `Using a SNAPSHOT release`_. - -To clone the ``cordapp-tutorial`` repository, use the following command: +Downloading the example CorDapp +------------------------------- +If you haven't already, set up your machine by following the :doc:`quickstart guide `. Then clone the +example CorDapp from the `cordapp-tutorial repository `_ using the following +command: ``git clone https://github.com/corda/cordapp-tutorial`` -Now change directories to the freshly cloned repo: +And change directories to the freshly cloned repo: ``cd cordapp-tutorial`` -To enumerate all the tagged releases. Use: +We want to work off the latest Milestone release. To enumerate all the Milestone releases, run: ``git tag`` -To checkout a specific tag, use: +And check out the latest (highest-numbered) Milestone release using: -``git checkout -b [local_branch_name] tags/[tag_name]`` +``git checkout [tag_name]`` -where ``local_branch_name`` is a name of your choice and ``tag_name`` is the name of the tag you wish to checkout. +Where ``tag_name`` is the name of the tag you wish to checkout. Gradle will grab all the required dependencies for you +from our `public Maven repository `_. -Gradle will handle all the dependencies for you. Now you are now ready to get started `building the example CorDapp`_. +.. note:: If you wish to build off the latest, unstable version of the codebase, follow the instructions in + `Using a SNAPSHOT release`_. -Using a SNAPSHOT release -~~~~~~~~~~~~~~~~~~~~~~~~ - -If you wish to build a CorDapp against the most current version of Corda, follow these instructions. - -Firstly navigate to the folder on your machine you wish to clone the Corda repository to. Then use the following command -to clone the Corda repository: - -``git clone https://github.com/corda/corda.git`` - -Now change directories: - -``cd corda`` - -Once you've cloned the ``corda`` repository and are in the repo directory you have the option to remain on the master -branch or checkout a specific branch. Use: - -``git branch --all`` - -to enumerate all the branches. To checkout a specific branch, use: - -``git checkout -b [local_branch_name] origin/[remote_branch_name]`` - -where ``local_branch_name`` is a name of your choice and ``remote_branch_name`` is the name of the remote branch you wish -to checkout. - -.. note:: When working with ``master`` you will have access to the most up-to-date feature set. However you will be - potentially sacrificing stability. We will endeavour to keep the ``master`` branch of the ``cordapp-tutorial`` repo in sync - with the ``master`` branch of ``corda`` repo. A milestone tagged release would be more stable for CorDapp development. - -The next step is to publish the Corda JARs to your local Maven repository. By default the Maven local repository can be -found: - -* ``~/.m2/repository`` on Unix/Mac OS X -* ``%HOMEPATH%\.m2`` on windows. - -Publishing can be done with running the following Gradle task from the root project directory: - -Unix/Mac OSX: ``./gradlew install`` - -Windows: ``gradlew.bat install`` - -This will install all required modules, along with sources and JavaDocs to your local Maven repository. The ``version`` -and ``groupid`` of Corda installed to Maven local is specified in the ``build.gradle`` file in the root of the ``corda`` -repository. You shouldn't have to change these values unless you want to publish multiple versions of a SNAPSHOT, e.g. -if you are trying out new features, in this case you can change ``version`` for each SNAPSHOT you publish. - -.. note:: **A quick point on corda version numbers used by Gradle.** - - In the ``build.gradle`` file for your CorDapp, you can specify the ``corda_release_version`` to use. It is important - that when developing your CorDapp that you use the correct version number. For example, when wanting to work from a SNAPSHOT - release, the release numbers are suffixed with 'SNAPSHOT', e.g. if the latest milestone release is M6 then the - SNAPSHOT release will be 0.7-SNAPSHOT, and so on. As such, you will set your ``corda_release_version`` to ``'0.7-SNAPSHOT'`` - in the ``build.gradle`` file in your CorDapp. Gradle will automatically grab the SNAPSHOT dependencies from your local - Maven repository. Alternatively, if working from a milestone release, you will use the version number only, for example - ``0.6`` or ``0.7``. - - Lastly, as the Corda repository evolves on a daily basis up until the next milestone release, it is worth nothing that - the substance of two SNAPSHOT releases of the same number may be different. If you are using a SNAPSHOT and need help - debugging an error then please tell us the **commit** you are working from. This will help us ascertain the issue. - -As additional feature branches are merged into Corda you can ``git pull`` the new changes from the ``corda`` repository. -If you are feeling inquisitive, you may also wish to review some of the current feature branches. All new features are -developed on separate branches. To enumerate all the current branches use: - -``git branch --all`` - -and to check out an open feature branch, use: - -``git checkout -b [local_branch_name] origin/[branch_name]`` - -.. note:: Publishing Corda JARs from unmerged feature branches might cause some unexpected behaviour / broken CorDapps. - It would also replace any previously published SNAPSHOTS of the same version. - -.. warning:: If you do modify Corda after you have previously published it to Maven local then you must republish your - SNAPSHOT build such that Maven reflects the changes you have made. - -Once you have published the Corda JARs to your local Maven repository, you are ready to get started building your -CorDapp using the latest Corda features. - -Opening the example CorDapp with IntelliJ -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -For those familiar with IntelliJ, you can skip this section. - -As noted in the getting started guide, we recommend using the IntelliJ IDE. Assuming you have already downloaded and -installed IntelliJ, lets now open the example CorDapp with IntelliJ. +Opening the example CorDapp in IntelliJ +--------------------------------------- +Let's open the example CorDapp in the IntelliJ IDE. **For those completely new to IntelliJ** -Firstly, load up IntelliJ. A dialogue will appear: +Upon opening IntelliJ, a dialogue will appear: .. image:: resources/intellij-welcome.png :width: 400 Click open, then navigate to the folder where you cloned the ``cordapp-tutorial`` and click OK. -Next, IntelliJ will show a bunch of pop-up windows. One of which requires our attention: +Next, IntelliJ will show several pop-up windows, one of which requires our attention: .. image:: resources/unlinked-gradle-project.png :width: 400 -Click the 'import gradle project' link. A dialogue will pop-up. Press OK. Gradle will now obtain all the -project dependencies and perform some indexing. It usually takes a minute or so. If you miss the 'import gradle project' -dialogue, simply close and re-open IntelliJ again to see it again. +Click the 'import gradle project' link. A dialogue will pop-up. Press OK. Gradle will now download all the +project dependencies and perform some indexing. This usually takes a minute or so. -**Alternative approach** - -Alternatively, one can instruct IntelliJ to create a new project through cloning a repository. From the IntelliJ welcome -dialogue (shown above), opt to 'check out from version control', then select git and enter the git URL for the example CorDapp -(https://github.com/corda/cordapp-tutorial). You'll then need to import the Gradle project when prompted, as explained above. +If the 'import gradle project' pop-up does not appear, click the small green speech bubble at the bottom-right of +the IDE, or simply close and re-open IntelliJ again to make it reappear. **If you already have IntelliJ open** -From the ``File`` menu, navigate to ``Open ...`` and then navigate to the directory where you cloned the ``cordapp-tutorial``. -Alternatively, if you wish to clone from github directly then navigate to ``File > New > Project from existing sources ...`` -and enter the URL to the example CorDapp (specified above). When instructed, be sure to import the Gradle project when prompted. +From the ``File`` menu, navigate to ``Open ...`` and then navigate to the directory where you cloned the +``cordapp-tutorial`` and click OK. -**The Gradle plugin** - -IntelliJ can be used to run Gradle tasks through the Gradle plugin which can be found via ``View > Tool windows > Gradle``. -All the Gradle projects are listed in the window on the right hand side of the IDE. Click on a project, then 'tasks' to -see all available Gradle tasks. - -* For the example CorDapp repo there will only be one Gradle project listed. -* For the Corda repo there will be many project listed, the root project ``corda`` and associated sub-projects: ``core``, - ``finance``, ``node``, etc. - -.. note:: It's worth noting that when you change branch in the example CorDapp, the ``corda_release_version`` will change to - reflect the version of the branch you are working from. - -To execute a task, double click it. The output will be shown in a console window. - -Building the example CorDapp ----------------------------- - -**From the command line** - -Firstly, return to your terminal window used above and make sure you are in the ``cordapp-tutorial`` directory. - -To build the example CorDapp use the following command: - -Unix/Mac OSX: ``./gradlew deployNodes`` - -Windows: ``gradlew.bat deployNodes`` - -This build process will build the example CorDapp defined in the example CorDapp source. CorDapps can be written in -any language targeting the JVM. In our case, we've provided the example source in both Kotlin (``/kotlin-source/src``) and -Java (``/java-source/src``) Since both sets of source files are functionally identical, we will refer to the Kotlin build -throughout the documentation. - -For more information on the example CorDapp see "The Example CorDapp" section below. Gradle will then grab all the -dependencies for you and build the example CorDapp. - -The ``deployNodes`` Gradle task allows you easily create a formation of Corda nodes. In the case of the example CorDapp -we are creating ``four`` nodes. - -After the building process has finished to see the newly built nodes, you can navigate to the ``kotlin-source/build/nodes`` folder -located in the ``cordapp-tutorial`` root directory. You can ignore the other folders in ``/build`` for now. The ``nodes`` -folder has the following structure: +Project structure +----------------- +The example CorDapp has the following directory structure: .. sourcecode:: none - . nodes - ├── controller - │   ├── corda.jar - │   ├── node.conf - │   └── plugins - ├── nodea - │   ├── corda.jar - │   ├── node.conf - │   └── plugins - ├── nodeb - │   ├── corda.jar - │   ├── node.conf - │   └── plugins - ├── nodec - │   ├── corda.jar - │   ├── node.conf - │   └── plugins - ├── runnodes - └── runnodes.bat + . + ├── LICENCE + ├── README.md + ├── TRADEMARK + ├── build.gradle + ├── config + │   ├── dev + │   │   └── log4j2.xml + │   └── test + │   └── log4j2.xml + ├── doc + │   └── example_flow.plantuml + ├── gradle + │   └── wrapper + │   ├── gradle-wrapper.jar + │   └── gradle-wrapper.properties + ├── gradle.properties + ├── gradlew + ├── gradlew.bat + ├── java-source + │   └── ... + ├── kotlin-source + │   ├── build.gradle + │   └── src + │   ├── main + │   │   ├── kotlin + │   │   │   └── com + │   │   │   └── example + │   │   │   ├── api + │   │   │   │   └── ExampleApi.kt + │   │   │   ├── client + │   │   │   │   └── ExampleClientRPC.kt + │   │   │   ├── contract + │   │   │   │   └── IOUContract.kt + │   │   │   ├── flow + │   │   │   │   └── ExampleFlow.kt + │   │   │   ├── model + │   │   │   │   └── IOU.kt + │   │   │   ├── plugin + │   │   │   │   └── ExamplePlugin.kt + │   │   │   ├── schema + │   │   │   │   └── IOUSchema.kt + │   │   │   └── state + │   │   │   └── IOUState.kt + │   │   └── resources + │   │   ├── META-INF + │   │   │   └── services + │   │   │   └── net.corda.webserver.services.WebServerPluginRegistry + │   │   ├── certificates + │   │   │   ├── readme.txt + │   │   │   ├── sslkeystore.jks + │   │   │   └── truststore.jks + │   │   └── exampleWeb + │   │   ├── index.html + │   │   └── js + │   │   └── angular-module.js + │   └── test + │   └── kotlin + │   └── com + │   └── example + │   ├── Main.kt + │   ├── contract + │   │   └── IOUContractTests.kt + │   └── flow + │   └── IOUFlowTests.kt + ├── lib + │   ├── README.txt + │   └── quasar.jar + └── settings.gradle -There will be one folder generated for each node you build (more on later when we get into the detail of the -``deployNodes`` Gradle task) and a ``runnodes`` shell script (batch file on Windows). +The most important files and directories to note are: -Each node folder contains the Corda JAR and a folder for plugins (or CorDapps). There is also -a node.conf file. See :doc:`Corda configuration files `. - -**Building from IntelliJ** - -Open the Gradle window by selecting ``View > Tool windows > Gradle`` from the main menu. You will see the Gradle window -open on the right hand side of the IDE. Expand `tasks` and then expand `other`. Double click on `deployNodes`. Gradle will -start the build process and output progress to a console window in the IDE. +* The **root directory** contains some gradle files, a README and a LICENSE +* **config** contains log4j 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 is required for runtime instrumentation of classes by Quasar +* **kotlin-source** contains the source code for the example CorDapp written in Kotlin + * **kotlin-source/src/main/kotlin** contains the source code for the example CorDapp + * **kotlin-source/src/main/python** contains a python script which accesses nodes via RPC + * **kotlin-source/src/main/resources** contains the certificate store, some static web content to be served by the + nodes and the WebServerPluginRegistry file + * **kotlin-source/src/test/kotlin** contains unit tests for the contracts and flows, and the driver to run the nodes + via IntelliJ +* **java-source** contains the same source code, but written in java. This is an aid for users who do not want to + develop in Kotlin, and serves as an example of how CorDapps can be developed in any language targeting the JVM Running the example CorDapp --------------------------- +There are two ways to run the example CorDapp: -To run the sample CorDapp navigate to the ``kotlin-source/build/nodes`` folder and execute the ``runnodes`` shell script with: +* Via the terminal +* Via IntelliJ -Unix: ``./runnodes`` or ``sh runnodes`` +We explain both below. -Windows: ``runnodes.bat`` +Terminal: Building the example CorDapp +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Return to your terminal window and make sure you are in the ``cordapp-tutorial`` directory. To build the example +CorDapp use the following command: -The ``runnodes`` scripts should create a terminal tab for each node. In each terminal tab, you'll see the Corda welcome -message and some pertinent config information, see below: +* Unix/Mac OSX: ``./gradlew deployNodes`` +* Windows: ``gradlew.bat deployNodes`` + +This will package up our CorDapp source files into a plugin and automatically build four pre-configured nodes that have +our CorDapp plugin installed. These nodes are meant for local testing only. + +After the build process has finished, you will see the newly-build nodes in the ``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). + +.. note:: CorDapps can be written in any language targeting the JVM. In our case, we've provided the example source in + both Kotlin (``/kotlin-source/src``) and Java (``/java-source/src``) Since both sets of source files are + functionally identical, we will refer to the Kotlin build throughout the documentation. + +Each node in the ``nodes`` folder has the following structure: .. sourcecode:: none - ______ __ - / ____/ _________/ /___ _ - / / __ / ___/ __ / __ `/ Computer science and finance together. - / /___ /_/ / / / /_/ / /_/ / You should see our crazy Christmas parties! - \____/ /_/ \__,_/\__,_/ + . nodeName + ├── corda.jar + ├── node.conf + └── plugins - --- DEVELOPER SNAPSHOT ------------------------------------------------------------ +``corda.jar` is the Corda runtime, ``plugins`` contains our node's CorDapps, and our node's configuration is provided +in ``node.conf``. - Logs can be found in : /Users/rogerwillis/Documents/Corda/cordapp-tutorial/kotlin-source/build/nodes/nodea/logs - Database connection URL is : jdbc:h2:tcp://10.18.0.196:50661/node - Node listening on address : localhost:10004 - Loaded plugins : com.example.plugin.ExamplePlugin - Embedded web server is listening on : http://10.18.0.196:10005/ - Node started up and registered in 39.0 sec +Terminal: Running the example CorDapp +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +To run our nodes, run the following command from the root of the ``cordapp-tutorial`` folder: -You'll need to refer to the above later on for the JDBC connection string and port numbers. +* Unix/Mac OSX: ``kotlin-source/build/nodes/runnodes`` +* Windows: ``call kotlin-source\build\nodes\runnodes.bat`` -Depending on the speed of your machine, it usually takes around 30 seconds for the nodes to finish starting up. If you -want to double check all the nodes are running you can query the 'status' end-point located at -``http://host:post/api/status``. +On Unix/Mac OSX, do not click/change focus until all eight additional terminal windows have opened, or some nodes may +fail to start. -When booted up, the node will generate a bunch of files and directories in addition to the ones covered above: +The ``runnodes`` script creates a terminal tab/window for each node: .. sourcecode:: none - . - ├── artemis - ├── attachments - ├── cache - ├── certificates - ├── corda.jar - ├── identity-private-key - ├── identity-public - ├── logs - ├── node.conf - ├── persistence.mv.db - └── plugins + ______ __ + / ____/ _________/ /___ _ + / / __ / ___/ __ / __ `/ It's kind of like a block chain but + / /___ /_/ / / / /_/ / /_/ / cords sounded healthier than chains. + \____/ /_/ \__,_/\__,_/ -Notably: + --- Corda Open Source 0.12.1 (da47f1c) ----------------------------------------------- -* **artemis** contains the internal files for Artemis MQ, our message broker. -* **attachments** contains any persisted attachments. -* **certificates** contains the certificate store. -* **identity-private-key** is the node's private key. -* **identity-public** is the node's public key. -* **logs** contains the node's log files. -* **persistence.mv.db** is the h2 database where transactions and other data is persisted. + 📚 New! Training now available worldwide, see https://corda.net/corda-training/ -Additional files and folders are added as the node is running. + Logs can be found in : /Users/joeldudley/Desktop/cordapp-tutorial/kotlin-source/build/nodes/NodeA/logs + Database connection url is : jdbc:h2:tcp://10.163.199.132:54763/node + Listening on address : 127.0.0.1:10005 + RPC service listening on address : localhost:10006 + Loaded plugins : com.example.plugin.ExamplePlugin + Node for "NodeA" started up and registered in 35.0 sec -Running the example CorDapp via IntelliJ -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -To run the example CorDapp via IntelliJ you can use the ``Run Example CorDapp`` run configuration. Select it from the drop -down menu at the top right-hand side of the IDE and press the green arrow to start the nodes. See image below: + 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 10:33:47 BST 2017>>> + +The script will also create a webserver terminal tab for each node: + +.. sourcecode:: none + + Logs can be found in /Users/joeldudley/Desktop/cordapp-tutorial/kotlin-source/build/nodes/NodeA/logs/web + Starting as webserver: localhost:10007 + Webserver started up in 42.02 sec + +Depending on your machine, it usually takes around 60 seconds for the nodes to finish starting up. If you want to +ensure that all the nodes are running OK, you can query the 'status' end-point located at +``http://localhost:[port]/api/status`` (e.g. ``http://localhost:10007/api/status`` for ``NodeA``). + +IntelliJ: Building and running the example CorDapp +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +To run the example CorDapp via IntelliJ you can use the ``Run Example CorDapp - Kotlin`` run configuration. Select it +from the drop-down menu at the top right-hand side of the IDE and press the green arrow to start the nodes: .. image:: resources/run-config-drop-down.png :width: 400 -The node driver defined in ``/src/main/kotlin-source/com/example/Main.kt`` allows you to specify how many nodes you would like -to run and the various configuration settings for each node. With the example CorDapp, the Node driver starts four nodes -and sets up an RPC user for all but the "Controller" node (which hosts the notary Service and network map service): +The node driver defined in ``/src/test/kotlin/com/example/Main.kt`` allows you to specify how many nodes you would like +to run and the configuration settings for each node. With the example CorDapp, the driver starts up four nodes +and adds an RPC user for all but the "Controller" node (which serves as the notary and network map service): .. sourcecode:: kotlin - fun main(args: Array) { - // No permissions required as we are not invoking flows. - val user = User("user1", "test", permissions = setOf()) - driver(dsl = { - startNode("Controller", setOf(ServiceInfo(ValidatingNotaryService.type))) - startNode("NodeA", rpcUsers = listOf(user)) - startNode("NodeB", rpcUsers = listOf(user)) - startNode("NodeC", rpcUsers = listOf(user)) - waitForAllNodesToFinish() - }, isDebug = true) - } + fun main(args: Array) { + // No permissions required as we are not invoking flows. + val user = User("user1", "test", permissions = setOf()) + driver(isDebug = true) { + startNode(X500Name("CN=Controller,O=R3,OU=corda,L=London,C=UK"), setOf(ServiceInfo(ValidatingNotaryService.type))) + val (nodeA, nodeB, nodeC) = Futures.allAsList( + startNode(X500Name("CN=NodeA,O=NodeA,L=London,C=UK"), rpcUsers = listOf(user)), + startNode(X500Name("CN=NodeB,O=NodeB,L=New York,C=US"), rpcUsers = listOf(user)), + startNode(X500Name("CN=NodeC,O=NodeC,L=Paris,C=FR"), rpcUsers = listOf(user))).getOrThrow() -To stop the nodes, press the red "stop" button at the top right-hand side of the IDE. + startWebserver(nodeA) + startWebserver(nodeB) + startWebserver(nodeC) -The node driver can also be used to as a basis for `debugging your CorDapp`_ + waitForAllNodesToFinish() + } + } + +To stop the nodes, press the red square button at the top right-hand side of the IDE, next to the run configurations. + +We'll look later at how the node driver can be useful for `debugging your CorDapp`_. Interacting with the example CorDapp ------------------------------------ Via HTTP ~~~~~~~~ +The CorDapp defines several HTTP API end-points and a web front-end. The end-points allow you to list your existing +IOUs, agree new IOUs, and see who is on the network. -The CorDapp defines a few HTTP API end-points and also serves some static web content. The end-points allow you to -list IOUs and add IOUs. +The nodes are running locally on the following ports: -The nodes can be found using the following port numbers, defined in build.gradle and the respective node.conf file for -each node found in `kotlin-source/build/nodes/NodeX`` etc: +* Controller: ``localhost:10004`` +* NodeA: ``localhost:10007`` +* NodeB: ``localhost:10010`` +* NodeC: ``localhost:10013`` -* Controller: ``localhost:10003`` -* NodeA: ``localhost:10005`` -* NodeB: ``localhost:10007`` -* NodeC: ``localhost:10009`` +These ports are defined in build.gradle and in each node's node.conf file under ``kotlin-source/build/nodes/NodeX``. -Note that the ``deployNodes`` Gradle task is used to generate the ``node.conf`` files for each node. - -As the nodes start-up they should tell you which host and port the embedded web server is running on. The API endpoints -served are as follows: +As the nodes start up, they should tell you which port their embedded web server is running on. The available API +endpoints are: * ``/api/example/me`` * ``/api/example/peers`` * ``/api/example/ious`` * ``/api/example/{COUNTERPARTY}/create-iou`` -The static web content is served from ``/web/example``. +The web front-end is served from ``/web/example``. -An IOU can be created via accessing the ``api/example/create-iou`` end-point directly or through the +An IOU can be created by sending a PUT request to the ``api/example/create-iou`` end-point directly, or by using the the web form hosted at ``/web/example``. - .. warning:: **The content in ``web/example`` is only available for demonstration purposes and does not implement any - anti-XSS, anti-XSRF or any other security techniques. Do not copy such code directly into products meant for production use.** +.. warning:: The content in ``web/example`` is only available for demonstration purposes and does not implement + anti-XSS, anti-XSRF or any other security techniques. Do not use this code in production. -**Submitting an IOU via HTTP API:** +**Creating an IOU via the HTTP API:** -To create an IOU from NodeA to NodeB, use: +To create an IOU between NodeA and NodeB, we would run the following from the command line: .. sourcecode:: bash - echo '{"value": "1"}' | cURL -T - -H 'Content-Type: application/json' http://localhost:10005/api/example/NodeB/create-iou + echo '{"value": "1"}' | cURL -T - -H 'Content-Type: application/json' http://localhost:10007/api/example/NodeB/create-iou -Note the port number ``10005`` (NodeA) and NodeB referenced in the API end-point path. This command instructs NodeA to -create and send an IOU to NodeB. Upon verification and completion of the process, both nodes (but not NodeC) will -have a signed, notarised copy of the IOU. +Note that both NodeA's port number (``10007``) and NodeB are referenced in the PUT request path. This command instructs +NodeA to agree an IOU with NodeB. Once the process is complete, both nodes will have a signed, notarised copy of the +IOU. NodeC will not. -**Submitting an IOU via web/example:** +**Submitting an IOU via the web front-end:** -Navigate to the "create IOU" button at the top left of the page, and enter the IOU details - e.g. +Navigate to ``/web/example``, 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 value of between 1 and 99. .. sourcecode:: none Counter-party: Select from list - Order Number: 1 - Delivery Date: 2018-09-15 - City: London - Country Code: GB - Item name: Wow such item - Item amount: 5 + Value (Int): 5 -and click submit (note you can add additional item types and amounts). Upon pressing submit, the modal dialogue should close. -To check what validation is performed over the IOU data, have a look at the ``IOUContract.Create`` class in -``IOUContract.kt`` which defines the following contract constraints (among others not included here): - -.. sourcecode:: kotlin - - // Generic constraints around the IOU transaction. - "No inputs should be consumed when issuing an IOU." using (tx.inputs.isEmpty()) - "Only one output state should be created." using (tx.outputs.size == 1) - val out = tx.outputs.single() as IOUState - "The sender and the recipient cannot be the same entity." using (out.sender != out.recipient) - "All of the participants must be signers." using (command.signers.containsAll(out.participants)) - - // IOU-specific constraints. - "The IOU's value must be non-negative." using (out.iou.value > 0) +And click submit. Upon clicking submit, the modal dialogue will close, and the nodes will agree the IOU. **Once an IOU has been submitted:** -Inspect the terminal windows for the nodes. Assume all of the above contract constraints are met, you should see some -activity in the terminal windows for NodeA and NodeB (note: the green ticks are only visible on unix/mac): - -*NodeA:* +Assuming all went well, you should see some activity in NodeA's web-server terminal window: .. sourcecode:: none - ✅ Generating transaction based on new IOU. - ✅ Verifying contract constraints. - ✅ Signing transaction with our private key. - ✅ Sending proposed transaction to recipient for review. - ✅ Done + >> Generating transaction based on new IOU. + >> Verifying contract constraints. + >> Signing transaction with our private key. + >> Gathering the counterparty's signature. + >> Structural step change in child of Gathering the counterparty's signature. + >> Collecting signatures from counter-parties. + >> Verifying collected signatures. + >> Done + >> Obtaining notary signature and recording transaction. + >> Structural step change in child of Obtaining notary signature and recording transaction. + >> Requesting signature by notary service + >> Broadcasting transaction to participants + >> Done + >> Done -*NodeB:* - -.. sourcecode:: none - - ✅ Receiving proposed transaction from sender. - ✅ Verifying signatures and contract constraints. - ✅ Signing proposed transaction with our private key. - ✅ 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 - -*NodeC:* - -.. sourcecode:: none - - You shouldn't see any activity. - -Next you can view the newly created IOU by accessing the vault of NodeA or NodeB: +You can view the newly-created IOU by accessing the vault of NodeA or NodeB: *Via the HTTP API:* -For NodeA. navigate to http://localhost:10005/api/example/ious. For NodeB, -navigate to http://localhost:10007/api/example/ious. +* NodeA's vault: Navigate to http://localhost:10007/api/example/ious +* NodeB's vault: Navigate to http://localhost:10010/api/example/ious *Via web/example:* -Navigate to http://localhost:10005/web/example the refresh button in the top left-hand side of the page. You should -see the newly created agreement on the page. +* NodeA: Navigate to http://localhost:10007/web/example and hit the "refresh" button +* NodeA: Navigate to http://localhost:10010/web/example and hit the "refresh" button -Using the h2 web console -~~~~~~~~~~~~~~~~~~~~~~~~ +If you access the vault or web front-end of NodeC (on ``localhost:10013``), there will be no IOUs. This is because +NodeC was not involved in this transaction. -You can connect to the h2 database to see the current state of the ledger, among other data such as the current state of -the network map cache. Firstly, navigate to the folder where you downloaded the h2 web console as part of the pre-requisites -section, above. Change directories to the bin folder: +Via the interactive shell (terminal only) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Once a node has been started via the terminal, it will display an interactive shell: -``cd h2/bin`` +.. sourcecode:: none -Where there are a bunch of shell scripts and batch files. Run the web console: + Welcome to the Corda interactive shell. + Useful commands include 'help' to see what is available, and 'bye' to shut down the node. -Unix: + Fri Jul 07 16:36:29 BST 2017>>> -``sh h2.sh`` +You can see a list of the flows that your node can run using `flow list`. In our case, this will return the following +list: -Windows: +.. sourcecode:: none -``h2.bat`` + com.example.flow.ExampleFlow$Initiator + net.corda.flows.CashExitFlow + net.corda.flows.CashIssueFlow + net.corda.flows.CashPaymentFlow + net.corda.flows.ContractUpgradeFlow -The h2 web console should start up in a web browser tab. To connect we first need to obtain a JDBC connection string. Each -node outputs its connection string in the terminal window as it starts up. In a terminal window where a node is running, -look for the following string: +We can create a new IOU using the ``ExampleFlow$Initiator`` flow. For example, from the interactive shell of NodeA, you +can agree an IOU of 50 with NodeB by running ``flow start Initiator iouValue: 50, otherParty: NodeB``. -``Database connection URL is : jdbc:h2:tcp://10.18.0.150:56736/node`` +This will print out the following progress steps: -you can use the string on the right to connect to the h2 database: just paste it in to the JDBC URL field and click Connect. -You will be presented with a web application that enumerates all the available tables and provides an interface for you to -query them using SQL. +.. sourcecode:: none -Using the Example RPC client + ✅ Generating transaction based on new IOU. + ✅ Verifying contract constraints. + ✅ Signing transaction with our private key. + ✅ Gathering the counterparty's signature. + ✅ Collecting signatures from counter-parties. + ✅ 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 + +We can also issue RPC operations to the node via the interactive shell. Type ``run`` to see the full list of available +operations. + +We can see a list of the states in our node's vault using ``run vaultAndUpdates``: + +.. sourcecode:: none + + --- + first: + - state: + data: + iou: + value: 50 + sender: "CN=NodeB,O=NodeB,L=New York,C=US" + recipient: "CN=NodeA,O=NodeA,L=London,C=UK" + linearId: + externalId: null + id: "84628565-2688-45ef-bb06-aae70fcf3be7" + contract: + legalContractReference: "4DDE2A47C361106CBAEC06CC40FE418A994822A3C8054851FEECD51207BFAF82" + participants: + - "CN=NodeB,O=NodeB,L=New York,C=US" + - "CN=NodeA,O=NodeA,L=London,C=UK" + notary: "CN=Controller,O=R3,OU=corda,L=London,C=UK,OU=corda.notary.validating" + encumbrance: null + ref: + txhash: "52A1B18E6ABD535EF36B2075469B01D2EF888034F721C4BECD26F40355C8C9DC" + index: 0 + second: "(observable)" + +We can also see the transactions stored in our node's local storage using ``run verifiedTransactions`` (we've +abbreviated the output below): + +.. sourcecode:: none + + first: + - txBits: "Y29yZGEAAAEOAQEAamF2YS51dGlsLkFycmF5TGlz9AABAAABAAEBAW5ldC5jb3JkYS5jb3JlLmNvbnRyYWN0cy5UcmFuc2FjdGlvblN0YXTlA1RyYW5zYWN0aW9uU3RhdGUuZGF04VRyYW5zYWN0aW9uU3RhdGUuZW5jdW1icmFuY+VUcmFuc2FjdGlvblN0YXRlLm5vdGFy+WkBAmNvbS5leGFtcGxlLnN0YXRlLklPVVN0YXTlBElPVVN0YXRlLmlv9UlPVVN0YXRlLmxpbmVhcknkSU9VU3RhdGUucmVjaXBpZW70SU9VU3RhdGUuc2VuZGXyDQEBSU9VLnZhbHXlAWQCAQA0ADIBAlVuaXF1ZUlkZW50aWZpZXIuZXh0ZXJuYWxJ5FVuaXF1ZUlkZW50aWZpZXIuaeQBgDAvAC0BAlVVSUQubGVhc3RTaWdCaXTzVVVJRC5tb3N0U2lnQml08wmxkIaDnsaq+YkNDAsACaHovZfbpr2d9wMCAQACAQBIAEYBAkFic3RyYWN0UGFydHkub3duaW5nS2X5UGFydHkubmFt5SIuIOnhdbFQY3EL/LQD90w6y+kCfj4x8UWXaqKtW68GBPlnREMAQTkwPjEOMAwGA1UEAwwFTm9kZUExDjAMBgNVBAoMBU5vZGVBMQ8wDQYDVQQHDAZMb25kb24xCzAJBgNVBAYTAlVLAgEAJgAkASIuIHI7goTSxPMdaRgJgGJVLQbFEzE++qJeYbEbQjrYxzuVRkUAQzkwQDEOMAwGA1UEAwwFTm9kZUIxDjAMBgNVBAoMBU5vZGVCMREwDwYDVQQHDAhOZXcgWW9yazELMAkGA1UEBhMCVVMCAQABAAABAAAkASIuIMqulslvpZ0PaM6fdyFZm+JsDGkuJ7xWnL3zB6PqpzANdwB1OTByMRMwEQYDVQQDDApDb250cm9sbGVyMQswCQYDVQQKDAJSMzEOMAwGA1UECwwFY29yZGExDzANBgNVBAcMBkxvbmRvbjELMAkGA1UEBhMCVUsxIDAeBgNVBAsMF2NvcmRhLm5vdGFyeS52YWxpZGF0aW5nAQAAAQABAQNuZXQuY29yZGEuY29yZS5jb250cmFjdHMuQ29tbWFu5AJDb21tYW5kLnNpZ25lcvNDb21tYW5kLnZhbHXlRwEAAi4gcjuChNLE8x1pGAmAYlUtBsUTMT76ol5hsRtCOtjHO5UuIOnhdbFQY3EL/LQD90w6y+kCfj4x8UWXaqKtW68GBPlnADMBBGNvbS5leGFtcGxlLmNvbnRyYWN0LklPVUNvbnRyYWN0JENvbW1hbmRzJENyZWF05QAAAQVuZXQuY29yZGEuY29yZS5pZGVudGl0eS5QYXJ0+SIuIMqulslvpZ0PaM6fdyFZm+JsDGkuJ7xWnL3zB6PqpzANAHU5MHIxEzARBgNVBAMMCkNvbnRyb2xsZXIxCzAJBgNVBAoMAlIzMQ4wDAYDVQQLDAVjb3JkYTEPMA0GA1UEBwwGTG9uZG9uMQswCQYDVQQGEwJVSzEgMB4GA1UECwwXY29yZGEubm90YXJ5LnZhbGlkYXRpbmcAAQACLiByO4KE0sTzHWkYCYBiVS0GxRMxPvqiXmGxG0I62Mc7lS4g6eF1sVBjcQv8tAP3TDrL6QJ+PjHxRZdqoq1brwYE+WcBBm5ldC5jb3JkYS5jb3JlLmNvbnRyYWN0cy5UcmFuc2FjdGlvblR5cGUkR2VuZXJh7AA=" + sigs: + - "cRgJlF8cUMMooyaV2OIKmR4/+3XmMsEPsbdlhU5YqngRhqgy9+tLzylh7kvWOhYZ4hjjOfrazLoZ6uOx6BAMCQ==" + - "iGLRDIbhlwguMz6yayX5p6vfQcAsp8haZc1cLGm7DPDIgq6hFyx2fzoI03DjXAV/mBT1upcUjM9UZ4gbRMedAw==" + id: "52A1B18E6ABD535EF36B2075469B01D2EF888034F721C4BECD26F40355C8C9DC" + tx: + inputs: [] + attachments: [] + outputs: + - data: + iou: + value: 50 + sender: "CN=NodeB,O=NodeB,L=New York,C=US" + recipient: "CN=NodeA,O=NodeA,L=London,C=UK" + linearId: + externalId: null + id: "84628565-2688-45ef-bb06-aae70fcf3be7" + contract: + legalContractReference: "4DDE2A47C361106CBAEC06CC40FE418A994822A3C8054851FEECD51207BFAF82" + participants: + - "CN=NodeB,O=NodeB,L=New York,C=US" + - "CN=NodeA,O=NodeA,L=London,C=UK" + notary: "CN=Controller,O=R3,OU=corda,L=London,C=UK,OU=corda.notary.validating" + encumbrance: null + commands: + - value: {} + signers: + - "8Kqd4oWdx4KQAVc3u5qvHZTGJxMtrShFudAzLUTdZUzbF9aPQcCZD5KXViC" + - "8Kqd4oWdx4KQAVcBx98LBHwXwC3a7hNptQomrg9mq2ScY7t1Qqsyk5dCNAr" + notary: "CN=Controller,O=R3,OU=corda,L=London,C=UK,OU=corda.notary.validating" + type: {} + timeWindow: null + mustSign: + - "8Kqd4oWdx4KQAVc3u5qvHZTGJxMtrShFudAzLUTdZUzbF9aPQcCZD5KXViC" + - "8Kqd4oWdx4KQAVcBx98LBHwXwC3a7hNptQomrg9mq2ScY7t1Qqsyk5dCNAr" + id: "52A1B18E6ABD535EF36B2075469B01D2EF888034F721C4BECD26F40355C8C9DC" + merkleTree: ... + availableComponents: ... + availableComponentHashes: ... + serialized: "Y29yZGEAAAEOAQEAamF2YS51dGlsLkFycmF5TGlz9AABAAABAAEBAW5ldC5jb3JkYS5jb3JlLmNvbnRyYWN0cy5UcmFuc2FjdGlvblN0YXTlA1RyYW5zYWN0aW9uU3RhdGUuZGF04VRyYW5zYWN0aW9uU3RhdGUuZW5jdW1icmFuY+VUcmFuc2FjdGlvblN0YXRlLm5vdGFy+WkBAmNvbS5leGFtcGxlLnN0YXRlLklPVVN0YXTlBElPVVN0YXRlLmlv9UlPVVN0YXRlLmxpbmVhcknkSU9VU3RhdGUucmVjaXBpZW70SU9VU3RhdGUuc2VuZGXyDQEBSU9VLnZhbHXlAWQCAQA0ADIBAlVuaXF1ZUlkZW50aWZpZXIuZXh0ZXJuYWxJ5FVuaXF1ZUlkZW50aWZpZXIuaeQBgDAvAC0BAlVVSUQubGVhc3RTaWdCaXTzVVVJRC5tb3N0U2lnQml08wmxkIaDnsaq+YkNDAsACaHovZfbpr2d9wMCAQACAQBIAEYBAkFic3RyYWN0UGFydHkub3duaW5nS2X5UGFydHkubmFt5SIuIOnhdbFQY3EL/LQD90w6y+kCfj4x8UWXaqKtW68GBPlnREMAQTkwPjEOMAwGA1UEAwwFTm9kZUExDjAMBgNVBAoMBU5vZGVBMQ8wDQYDVQQHDAZMb25kb24xCzAJBgNVBAYTAlVLAgEAJgAkASIuIHI7goTSxPMdaRgJgGJVLQbFEzE++qJeYbEbQjrYxzuVRkUAQzkwQDEOMAwGA1UEAwwFTm9kZUIxDjAMBgNVBAoMBU5vZGVCMREwDwYDVQQHDAhOZXcgWW9yazELMAkGA1UEBhMCVVMCAQABAAABAAAkASIuIMqulslvpZ0PaM6fdyFZm+JsDGkuJ7xWnL3zB6PqpzANdwB1OTByMRMwEQYDVQQDDApDb250cm9sbGVyMQswCQYDVQQKDAJSMzEOMAwGA1UECwwFY29yZGExDzANBgNVBAcMBkxvbmRvbjELMAkGA1UEBhMCVUsxIDAeBgNVBAsMF2NvcmRhLm5vdGFyeS52YWxpZGF0aW5nAQAAAQABAQNuZXQuY29yZGEuY29yZS5jb250cmFjdHMuQ29tbWFu5AJDb21tYW5kLnNpZ25lcvNDb21tYW5kLnZhbHXlRwEAAi4gcjuChNLE8x1pGAmAYlUtBsUTMT76ol5hsRtCOtjHO5UuIOnhdbFQY3EL/LQD90w6y+kCfj4x8UWXaqKtW68GBPlnADMBBGNvbS5leGFtcGxlLmNvbnRyYWN0LklPVUNvbnRyYWN0JENvbW1hbmRzJENyZWF05QAAAQVuZXQuY29yZGEuY29yZS5pZGVudGl0eS5QYXJ0+SIuIMqulslvpZ0PaM6fdyFZm+JsDGkuJ7xWnL3zB6PqpzANAHU5MHIxEzARBgNVBAMMCkNvbnRyb2xsZXIxCzAJBgNVBAoMAlIzMQ4wDAYDVQQLDAVjb3JkYTEPMA0GA1UEBwwGTG9uZG9uMQswCQYDVQQGEwJVSzEgMB4GA1UECwwXY29yZGEubm90YXJ5LnZhbGlkYXRpbmcAAQACLiByO4KE0sTzHWkYCYBiVS0GxRMxPvqiXmGxG0I62Mc7lS4g6eF1sVBjcQv8tAP3TDrL6QJ+PjHxRZdqoq1brwYE+WcBBm5ldC5jb3JkYS5jb3JlLmNvbnRyYWN0cy5UcmFuc2FjdGlvblR5cGUkR2VuZXJh7AA=" + second: "(observable)" + +The same states and transactions will be present on NodeB, who was NodeA's counterparty in the creation of the IOU. +However, the vault and local storage of NodeC will remain empty, since NodeC was not involved in the transaction. + +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 :doc:`node-database`. + +Using the example RPC client ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +The ``/src/main/kotlin-source/com/example/client/ExampleClientRPC.kt`` file is a simple utility that uses the client +RPC library to connect to a node. It will log any existing IOUs and listen for any future IOUs. If you haven't created +any IOUs when you first connect to one of the nodes, the client will simply log any future IOUs that are agreed. -The ``/src/main/kotlin-source/com/example/client/ExampleClientRPC.kt`` file is a simple utility which uses the client RPC library -to connect to a node and log the created IOUs. It will log any existing IOUs and listen for any future -IOUs. If you haven't created any IOUs when you connect to one of the Nodes via RPC then the client will log -and future IOUs which are agreed. +*Running the client via IntelliJ:* -To build the client use the following gradle task: - -``./gradlew runExampleClientRPC`` - -*To run the client, via IntelliJ:* - -Select the 'Run Example RPC Client' run configuration which, by default, connects to NodeA (Artemis port 10004). Click the +Select the 'Run Example RPC Client' run configuration which, by default, connects to NodeA (Artemis port 10007). Click the Green Arrow to run the client. You can edit the run configuration to connect on a different port. -*Via command line:* +*Running the client via the command line:* Run the following gradle task: -``./gradlew runExampleClientRPC localhost:10004`` +``./gradlew runExampleClientRPC localhost:10007`` -To close the application use ``ctrl+C``. For more information on the client RPC interface and how to build an RPC client -application see: +You can close the application using ``ctrl+C``. + +For more information on the client RPC interface and how to build an RPC client application, see: * :doc:`Client RPC documentation ` * :doc:`Client RPC tutorial ` -Extending the example CorDapp ------------------------------ - -cordapp-tutorial project structure -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -The example CorDapp has the following directory structure: - -.. sourcecode:: none - - . cordapp-tutorial - ├── README.md - ├── LICENSE - ├── build.gradle - ├── config - │   ├── ... - ├── gradle - │   └── ... - ├── gradle.properties - ├── gradlew - ├── gradlew.bat - ├── lib - │   ├── ... - ├── settings.gradle - ├── kotlin-source - │ └── src - │ ├── main - │    │   ├── kotlin - │    │   │   └── com - │    │   │   └── example - │    │   │   ├── Main.kt - │    │   │   ├── api - │    │   │   │   └── ExampleApi.kt - │    │   │   ├── client - │    │   │   │   └── ExampleClientRPC.kt - │    │   │   ├── contract - │    │   │   │   ├── IOUContract.kt - │    │   │   │   └── IOUState.kt - │    │   │   ├── model - │    │   │   │   └── IOU.kt - │    │   │   ├── plugin - │    │   │   │   └── ExamplePlugin.kt - │    │   │   └── flow - │    │   │   └── ExampleFlow.kt - │    │   │   └── service - │    │   │   └── ExampleService.kt - │ │   ├── python - │ │   └── resources - │ │   ├── META-INF - │ │   │   └── services - │   │   │   ├── net.corda.core.node.CordaPluginRegistry - │   │ │ └── net.corda.webserver.services.WebServerPluginRegistry - │ │   ├── certificates - │ │   │   ├── readme.txt - │ │   │   ├── sslkeystore.jks - │ │   │   └── truststore.jks - │ │   └── exampleWeb - │ │   ├── index.html - │ │   └── js - │ │   └── example.js - │ └── test - │ ├── java - │ ├── kotlin - │ │   └── com - │ │   └── example - │ │   └── ExampleTest.kt - │    └── resources - └── java-source - └── src - ├── main -    │   ├── java -    │   │   └── com -    │   │   └── example -    │   │   ├── Main.java -    │   │   ├── api -    │   │   │   └── ExampleApi.java -    │   │   ├── client -    │   │   │   └── ExampleClientRPC.java -    │   │   ├── contract -    │   │   │   ├── IOUContract.java -    │   │   │   └── IOUState.java -    │   │   ├── model -    │   │   │   └── IOU.java -    │   │   ├── plugin -    │   │   │   └── ExamplePlugin.java -    │   │   └── flow -    │   │   └── ExampleFlow.java -    │   │   └── service -    │   │   └── ExampleService.java - │   ├── python - │   └── resources - │   ├── META-INF - │   │   └── services -    │   │   ├── net.corda.core.node.CordaPluginRegistry -    │ │ └── net.corda.webserver.services.WebServerPluginRegistry - │   ├── certificates - │   │   ├── readme.txt - │   │   ├── sslkeystore.jks - │   │   └── truststore.jks - │   └── exampleWeb - │   ├── index.html - │   └── js - │   └── example.js - └── test - ├── java - ├── kotlin - │   └── com - │   └── example - │   └── ExampleTest.kt -    └── resources - -In the file structure above, the most important files and directories to note are: - -* The **root directory** contains some gradle files, a README and a LICENSE. -* **config** contains log4j 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 is required for runtime instrumentation of classes by Quasar. -* **kotlin-source** contains the source code for the example CorDapp written in Kotlin. - * **kotlin-source/src/main/kotlin** contains the source code for the example CorDapp. - * **kotlin-source/src/main/python** contains a python script which accesses nodes via RPC. - * **kotlin-source/src/main/resources** contains the certificate store, some static web content to be served by the nodes and the - PluginServiceRegistry file. - * **kotlin-source/src/test/kotlin** contains unit tests for protocols, contracts, etc. -* **java-source** contains the same source code, but written in java. This is an aid for users who do not want to develop in - Kotlin, and serves as an example of how CorDapps can be developed in any language targeting the JVM. - -Some elements are covered in more detail below. - -The build.gradle file -~~~~~~~~~~~~~~~~~~~~~ - -It is usually necessary to make a couple of changes to the ``build.gradle`` file. Here will cover the most pertinent bits. - -**The buildscript** - -The buildscript is always located at the top of the file. It determines which plugins, task classes, and other classes -are available for use in the rest of the build script. It also specifies version numbers for dependencies, among other -things. - -If you are working from a Corda SNAPSHOT release which you have publish to Maven local then ensure that -``corda_release_version`` is the same as the version of the Corda core modules you published to Maven local. If not then -change the ``kotlin_version`` property. Also, if you are working from a previous cordapp-tutorial milestone release, then -be sure to ``git checkout`` the correct version of the example CorDapp from the ``cordapp-tutorial`` repo. - -.. sourcecode:: groovy - - buildscript { - ext.kotlin_version = '1.0.4' - ext.corda_release_version = '0.5-SNAPSHOT' // Ensure this version is the same as the corda core modules you are using. - ext.quasar_version = '0.7.6' - ext.jersey_version = '2.23.1' - - repositories { - ... - } - - dependencies { - ... - } - } - -**Project dependencies** - -If you have any additional external dependencies for your CorDapp then add them below the comment at the end of this -code snippet.package. Use the standard format: - -``compile "{groupId}:{artifactId}:{versionNumber}"`` - -.. sourcecode:: groovy - - dependencies { - compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" - testCompile group: 'junit', name: 'junit', version: '4.11' - - // Corda integration dependencies - compile "net.corda:client:$corda_release_version" - compile "net.corda:core:$corda_release_version" - compile "net.corda:contracts:$corda_release_version" - compile "net.corda:node:$corda_release_version" - compile "net.corda:corda:$corda_release_version" - compile "net.corda:test-utils:$corda_release_version" - - ... - - // Cordapp dependencies - // Specify your cordapp's dependencies below, including dependent cordapps - } - -For further information about managing dependencies with `look at the Gradle docs `_. - -**CordFormation** - -This is the local node deployment system for CorDapps, the nodes generated are intended to be used for experimenting, -debugging, and testing node configurations but not intended for production or testnet deployment. - -In the CorDapp build.gradle file you'll find a ``deployNodes`` task, this is where you configure the nodes you would -like to deploy for testing. See further details below: - -.. sourcecode:: groovy - - task deployNodes(type: com.r3corda.plugins.Cordform, dependsOn: ['jar']) { - directory "./kotlin-source/build/nodes" // The output directory. - networkMap "CN=Controller,O=R3,OU=corda,L=London,C=GB" // The distinguished name of the node to be used as the network map. - node { - name "CN=Controller,O=R3,OU=corda,L=London,C=GB" // Distinguished name of node to be deployed. - advertisedServices = ["corda.notary.validating"] // A list of services you wish the node to offer. - p2pPort 10002 - rpcPort 10003 // Usually 1 higher than the messaging port. - webPort 10004 // Usually 1 higher than the RPC port. - cordapps = [] // Add package names of CordaApps. - } - node { // Create an additional node. - name "CN=NodeA,O=R3,OU=corda,L=London,C=GB" - advertisedServices = [] - p2pPort 10005 - rpcPort 10006 - webPort 10007 - cordapps = [] - } - ... - } - -You can add any number of nodes, with any number of services / CorDapps by editing the templates in ``deployNodes``. The -only requirement is that you must specify a node to run as the network map service and one as the notary service. - -.. note:: CorDapps in the current cordapp-tutorial project are automatically registered with all nodes defined in - ``deployNodes``, although we expect this to change in the near future. - -.. warning:: Make sure that there are no port clashes! - -When you are finished editing your *CordFormation* the changes will be reflected the next time you run ``./gradlew deployNodes``. - -Service Provider Configuration File -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -If you are building a CorDapp from scratch or adding a new CorDapp to the cordapp-tutorial project then you must provide -a reference to your sub-class of ``CordaPluginRegistry`` or ``WebServerPluginRegistry`` (for Wep API) in the provider-configuration file -located in the ``resources/META-INF/services`` directory. - -Re-Deploying Your Nodes Locally -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -If you need to create any additional nodes you can do it via the ``build.gradle`` file as discussed above in -``the build.gradle file`` and in more detail in the "cordFormation" section. - -You may also wish to edit the ``/kotlin-source/build/nodes//node.conf`` files for your nodes. For more information on -doing this, see the :doc:`Corda configuration file ` page. - -Once you have made some changes to your CorDapp you can redeploy it with the following command: - -Unix/Mac OSX: ``./gradlew deployNodes`` - -Windows: ``gradlew.bat deployNodes`` - Running Nodes Across Machines -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -The nodes can also be set up to communicate between separate machines on the -same subnet. +----------------------------- +The nodes can also be configured to communicate across the network when residing on different machines. After deploying the nodes, navigate to the build folder (``kotlin-source/build/nodes`` or ``java-source/build/nodes``) -and move some of the individual node folders to separate machines on the same subnet (e.g. using a USB key). -It is important that no nodes - including the controller node - end up on more than one machine. Each computer -should also have a copy of ``runnodes`` and ``runnodes.bat``. +and move some of the individual node folders to separate machines (e.g. using a USB key). It is important that none of +the nodes - including the controller node - 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: @@ -843,45 +560,49 @@ You must now edit the configuration file for each node, including the controller and make the following changes: * Change the Artemis messaging address to the machine's IP address (e.g. ``p2pAddress="10.18.0.166:10006"``) -* Change the network map service details to the IP address of the machine where the - controller node is running and to its legal name (e.g. ``networkMapService.address="10.18.0.166:10002"`` and - ``networkMapService.legalName=controller``) (please note that the controller will not have the ``networkMapService`` config) +* Change the network map service's address to the IP address of the machine where the controller node is running + (e.g. ``networkMapService { address="10.18.0.166:10002" ...``). The controller will not have the + ``networkMapService`` config -Now run each node. +After starting each node, they should be able to see one another and agree IOUs among themselves. Debugging your CorDapp -~~~~~~~~~~~~~~~~~~~~~~ +---------------------- +Debugging is done via IntelliJ as follows: -Debugging is done via IntelliJ and can be done using the following steps. - -1. Set your breakpoints. -2. Edit the node driver code in ``Main.kt`` to reflect how many nodes you wish to start along with any other - configuration options. For example, the below starts 4 nodes, with one being the network map service / notary and - sets up RPC credentials for 3 of the nodes. +1. Edit the node driver code in ``Main.kt`` to reflect the number of nodes you wish to start, along with any other + configuration options. For example, the code below starts 4 nodes, with one being the network map service and notary. + It also sets up RPC credentials for the three non-notary nodes .. sourcecode:: kotlin fun main(args: Array) { // No permissions required as we are not invoking flows. val user = User("user1", "test", permissions = setOf()) - driver(dsl = { - startNode("Controller", setOf(ServiceInfo(ValidatingNotaryService.type))) - startNode("NodeA", rpcUsers = listOf(user)) - startNode("NodeB", rpcUsers = listOf(user)) - startNode("NodeC", rpcUsers = listOf(user)) + driver(isDebug = true) { + startNode(X500Name("CN=Controller,O=R3,OU=corda,L=London,C=UK"), setOf(ServiceInfo(ValidatingNotaryService.type))) + val (nodeA, nodeB, nodeC) = Futures.allAsList( + startNode(X500Name("CN=NodeA,O=NodeA,L=London,C=UK"), rpcUsers = listOf(user)), + startNode(X500Name("CN=NodeB,O=NodeB,L=New York,C=US"), rpcUsers = listOf(user)), + startNode(X500Name("CN=NodeC,O=NodeC,L=Paris,C=FR"), rpcUsers = listOf(user))).getOrThrow() + + startWebserver(nodeA) + startWebserver(nodeB) + startWebserver(nodeC) + waitForAllNodesToFinish() - }, isDebug = true) + } } -3. Select and run the “Run Example CorDapp” run configuration in IntelliJ. -4. IntelliJ will build and run the CorDapp. Observe the console output for the remote debug ports. The “Controller” - node will generally be on port 5005, with NodeA on port 5006 an so-on. +2. Select and run the “Run Example CorDapp” run configuration in IntelliJ +3. IntelliJ will build and run the CorDapp. The remote debug ports for each node will be automatically generated and + printed to the terminal. For example: .. sourcecode:: none - Listening for transport dt_socket at address: 5008 - Listening for transport dt_socket at address: 5007 - Listening for transport dt_socket at address: 5006 + [INFO ] 15:27:59.533 [main] Node.logStartupInfo - Working Directory: /Users/joeldudley/cordapp-tutorial/build/20170707142746/NodeA + [INFO ] 15:27:59.533 [main] Node.logStartupInfo - Debug port: dt_socket:5007 -5. Edit the “Debug CorDapp” run configuration with the port of the node you wish to connect to. -6. Run the “Debug CorDapp” run configuration. +4. Edit the “Debug CorDapp” run configuration with the port of the node you wish to connect to +5. Run the “Debug CorDapp” run configuration +6. Set your breakpoints and start using your node. When your node hits a breakpoint, execution will pause \ No newline at end of file