Adds information on writing CorDapps. Reorg.

This commit is contained in:
Joel Dudley 2017-07-25 09:26:35 +01:00 committed by GitHub
parent 407b467f67
commit 5eb8b36809
5 changed files with 132 additions and 162 deletions

View File

@ -18,16 +18,52 @@ an ongoing stream of updates from the node. More detail on how to use this is pr
For a brief tutorial on how one can use the RPC API see :doc:`tutorial-clientrpc-api`.
Security
--------
RPC permissions
---------------
If a node's owner needs to interact with their node via RPC (e.g. to read the contents of the node's storage), they
must define one or more RPC users. Each user is authenticated with a username and password, and is assigned a set of
permissions that RPC can use for fine-grain access control.
Users wanting to use the RPC library are first required to authenticate themselves with the node using a valid username
and password. These are specified in the configuration file. Each user can be configured with a set of permissions which
the RPC can use for fine-grain access control.
These users are added to the node's ``node.conf`` file.
The syntax for adding an RPC user is:
.. container:: codeset
.. sourcecode:: groovy
rpcUsers=[
{
username=exampleUser
password=examplePass
permissions=[]
}
...
]
Currently, users need special permissions to start flows via RPC. These permissions are added as follows:
.. container:: codeset
.. sourcecode:: groovy
rpcUsers=[
{
username=exampleUser
password=examplePass
permissions=[
"StartFlow.net.corda.flows.ExampleFlow1",
"StartFlow.net.corda.flows.ExampleFlow2"
]
}
...
]
.. note:: Currently, the node's web server has super-user access, meaning that it can run any RPC operation without
logging in. This will be changed in a future release.
Observables
-----------
The RPC system handles observables in a special way. When a method returns an observable, whether directly or
as a sub-object of the response object graph, an observable is created on the client to match the one on the
server. Objects emitted by the server-side observable are pushed onto a queue which is then drained by the client.
@ -47,13 +83,11 @@ will be freed automatically.
Futures
-------
A method can also return a ``ListenableFuture`` in its object graph and it will be treated in a similar manner to
observables. Calling the ``cancel`` method on the future will unsubscribe it from any future value and release any resources.
Versioning
----------
The client RPC protocol is versioned using the node's Platform Version (see :doc:`versioning`). When a proxy is created
the server is queried for its version, and you can specify your minimum requirement. Methods added in later versions
are tagged with the ``@RPCSinceVersion`` annotation. If you try to use a method that the server isn't advertising support
@ -62,14 +96,12 @@ of, an ``UnsupportedOperationException`` is thrown. If you want to know the vers
Thread safety
-------------
A proxy is thread safe, blocking, and allows multiple RPCs to be in flight at once. Any observables that are returned and
you subscribe to will have objects emitted in order on a background thread pool. Each Observable stream is tied to a single
thread, however note that two separate Observables may invoke their respective callbacks on different threads.
Error handling
--------------
If something goes wrong with the RPC infrastructure itself, an ``RPCException`` is thrown. If you call a method that
requires a higher version of the protocol than the server supports, ``UnsupportedOperationException`` is thrown.
Otherwise, if the server implementation throws an exception, that exception is serialised and rethrown on the client
@ -77,18 +109,13 @@ side as if it was thrown from inside the called RPC method. These exceptions can
Wire protocol
-------------
The client RPC wire protocol is defined and documented in ``net/corda/client/rpc/RPCApi.kt``.
Whitelisting classes with the Corda node
----------------------------------------
To avoid the RPC interface being wide open to all
classes on the classpath, Cordapps have to whitelist any classes they require with the serialization framework of Corda,
if they are not one of those whitelisted by default in ``DefaultWhitelist``, via either the plugin architecture or simply
with the annotation ``@CordaSerializable``. See :doc:`running-a-node` or :doc:`serialization`. An example is shown in :doc:`tutorial-clientrpc-api`.
.. warning:: We will be replacing the use of Kryo in the serialization framework and so additional changes here are likely.
CorDapps must whitelist any classes used over RPC with Corda's serialization framework, unless they are whitelisted by
default in ``DefaultWhitelist``. The whitelisting is done either via the plugin architecture or by using the
``@CordaSerializable`` annotation. See :doc:`serialization`. An example is shown in :doc:`tutorial-clientrpc-api`.
.. _CordaRPCClient: api/javadoc/net/corda/client/rpc/CordaRPCClient.html
.. _CordaRPCOps: api/javadoc/net/corda/core/messaging/CordaRPCOps.html

View File

@ -1,48 +1,12 @@
Deploying a node
================
Building nodes using Gradle
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.
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 <https://docs.gradle.org/current/userguide/dependency_management.html>`_.
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.

View File

@ -3,14 +3,12 @@ Running a node
Starting your node
------------------
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 ``<node_dir>`` in a terminal window and running:
already installed. You run each node by navigating to ``<node_dir>`` in a terminal window and running:
.. code-block:: shell
Windows: java -jar corda.jar
UNIX: ./corda.jar
java -jar corda.jar
.. warning:: If your working directory is not ``<node_dir>`` your plugins and configuration will not be used.
@ -22,25 +20,8 @@ Otherwise the workspace folder for the node is the current working path.
Debugging your node
-------------------
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 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
a JDBC connection at the URL that is output to the logs at node start up. That URL will be of the form ``jdbc:h2:tcp://<host>:<port>/node``.
The user name and password for the login are as per the node data source configuration.
The name and column layout of the internal node tables is in a state of flux and should not be relied upon to remain static
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

View File

@ -37,3 +37,6 @@ It's reproduced here as an example of both ways you can do this for a couple of
.. note:: Several of the core interfaces at the heart of Corda are already annotated and so any classes that implement
them will automatically be whitelisted. This includes `Contract`, `ContractState` and `CommandData`.
.. warning:: We will be replacing the use of Kryo in the serialization framework and so additional changes here are
likely.

View File

@ -1,7 +1,8 @@
Writing a CorDapp
=================
The source-code for a CorDapp is a set of files written in a JVM language that defines a set of Corda components:
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``)
@ -9,14 +10,14 @@ The source-code for a CorDapp is a set of files written in a JVM language that d
* Web APIs
* Services
These files should be placed under ``src/main/[java|kotlin]``. The CorDapp's resources folder (``src/main/resources``)
should also include the following subfolders:
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.
* ``src/main/resources/certificates``, containing the node's certificates
* ``src/main/resources/META-INF/services``, containing a file named ``net.corda.core.node.CordaPluginRegistry``
For example, the source-code of the `Template CorDapp <https://github.com/corda/cordapp-template>`_ has the following
structure:
The ``src`` directory of the Template CorDapp, where we define our CorDapp's source-code, has the following structure:
.. parsed-literal::
@ -59,87 +60,81 @@ structure:
└── contract
└── TemplateTests.java
Defining a plugin
-----------------
You can specify the transport options (between nodes and between Web Client and a node) for your CorDapp by subclassing
``net.corda.core.node.CordaPluginRegistry``:
The build file
--------------
At the root of the Template CorDapp, you will also find a ``build.gradle`` file. This file is useful for several
reasons:
* The ``customizeSerialization`` function allows classes to be whitelisted for object serialisation, over and
above those tagged with the ``@CordaSerializable`` annotation. For instance, new state types will need to be
explicitly registered. In general, the annotation should be preferred. See :doc:`serialization`.
Choosing your CorDapp version
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
The following two lines of the ``build.gradle`` file define the Corda version used to build your CorDapp:
The fully-qualified class path of each ``CordaPluginRegistry`` subclass must be added to the
``net.corda.core.node.CordaPluginRegistry`` file in the CorDapp's ``resources/META-INF/services`` folder. A CorDapp
can register multiple plugins in a single ``net.corda.core.node.CordaPluginRegistry`` file.
.. sourcecode:: groovy
You can specify the web APIs and static web content for your CorDapp by implementing
``net.corda.webserver.services.WebServerPluginRegistry`` interface:
ext.corda_release_version = '0.13.0'
ext.corda_gradle_plugins_version = '0.13.3'
* The ``webApis`` property is a list of JAX-RS annotated REST access classes. These classes will be constructed by
the bundled web server and must have a single argument constructor taking a ``CordaRPCOps`` object. This will
allow the API to communicate with the node process via the RPC interface. These web APIs will not be available if the
bundled web server is not started.
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.
``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.
In certain cases, you may also wish to build against the unstable Master branch. See :doc:`building-against-master`.
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 <https://docs.gradle.org/current/userguide/dependency_management.html>`_.
Build tasks
^^^^^^^^^^^
The build file also defines a number of build tasks that will allow us to package up our plugin. We will discuss these
later.
Defining plugins
----------------
Your CorDapp may need to define two types of plugins:
* ``CordaPluginRegistry`` subclasses, which define additional serializable classes and vault schemas
* ``WebServerPluginRegistry`` subclasses, which define the APIs and static web content served by your CorDapp
The fully-qualified class path of each ``CordaPluginRegistry`` subclass must then be added to the
``net.corda.core.node.CordaPluginRegistry`` file in the CorDapp's ``resources/META-INF/services`` folder. Meanwhile,
the fully-qualified class path of each ``WebServerPluginRegistry`` subclass must be added to the
``net.corda.webserver.services.WebServerPluginRegistry`` file, again in the CorDapp's ``resources/META-INF/services``
folder.
The ``CordaPluginRegistry`` class defines the following:
* ``customizeSerialization``, which can be overridden to provide a list of the classes to be whitelisted for object
serialisation, over and above those tagged with the ``@CordaSerializable`` annotation. See :doc:`serialization`
* ``requiredSchemas``, which can be overridden to return a set of the MappedSchemas to use for persistence and vault
queries
The ``WebServerPluginRegistry`` class defines the following:
* ``webApis``, which can be overridden to return a list of JAX-RS annotated REST access classes. These classes will be
constructed by the bundled web server and must have a single argument constructor taking a ``CordaRPCOps`` object.
This will allow the API to communicate with the node process via the RPC interface. These web APIs will not be
available if the bundled web server is not started
* ``staticServeDirs``, which can be overridden to map static web content to virtual paths and allow simple web demos to
be distributed within the CorDapp jars. This static content will not be available if the bundled web server is not
started
* The ``staticServeDirs`` property maps static web content to virtual paths and allows simple web demos to be
distributed within the CorDapp jars. These static serving directories will not be available if the bundled web server
is not started.
* The static web content itself should be placed inside the ``src/main/resources`` directory
The fully-qualified class path of each ``WebServerPluginRegistry`` class must be added to the
``net.corda.webserver.services.WebServerPluginRegistry`` file in the CorDapp's ``resources/META-INF/services`` folder. A CorDapp
can register multiple plugins in a single ``net.corda.webserver.services.WebServerPluginRegistry`` file.
Installing CorDapps
-------------------
To run a CorDapp, its source is compiled into a JAR by running the gradle ``jar`` task. The CorDapp JAR is then added
to a node by adding it to the node's ``<node_dir>/plugins/`` folder (where ``node_dir`` is the folder in which the
node's JAR and configuration files are stored).
.. note:: Any external dependencies of your CorDapp will automatically be placed into the
``<node_dir>/dependencies/`` folder. This will be changed in a future release.
.. note:: Building nodes using the gradle ``deployNodes`` task will place the CorDapp JAR into each node's ``plugins``
folder automatically.
At runtime, nodes will load any plugins present in their ``plugins`` folder.
RPC permissions
---------------
If a node's owner needs to interact with their node via RPC (e.g. to read the contents of the node's storage), they
must define one or more RPC users. These users are added to the node's ``node.conf`` file.
The syntax for adding an RPC user is:
.. container:: codeset
.. sourcecode:: groovy
rpcUsers=[
{
username=exampleUser
password=examplePass
permissions=[]
}
...
]
Currently, users need special permissions to start flows via RPC. These permissions are added as follows:
.. container:: codeset
.. sourcecode:: groovy
rpcUsers=[
{
username=exampleUser
password=examplePass
permissions=[
"StartFlow.net.corda.flows.ExampleFlow1",
"StartFlow.net.corda.flows.ExampleFlow2"
]
}
...
]
.. note:: Currently, the node's web server has super-user access, meaning that it can run any RPC operation without
logging in. This will be changed in a future release.