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`. 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 These users are added to the node's ``node.conf`` file.
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. 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 Observables
----------- -----------
The RPC system handles observables in a special way. When a method returns an observable, whether directly or 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 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. 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 Futures
------- -------
A method can also return a ``ListenableFuture`` in its object graph and it will be treated in a similar manner to 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. observables. Calling the ``cancel`` method on the future will unsubscribe it from any future value and release any resources.
Versioning Versioning
---------- ----------
The client RPC protocol is versioned using the node's Platform Version (see :doc:`versioning`). When a proxy is created 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 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 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 Thread safety
------------- -------------
A proxy is thread safe, blocking, and allows multiple RPCs to be in flight at once. Any observables that are returned and 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 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. thread, however note that two separate Observables may invoke their respective callbacks on different threads.
Error handling Error handling
-------------- --------------
If something goes wrong with the RPC infrastructure itself, an ``RPCException`` is thrown. If you call a method that 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. 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 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 Wire protocol
------------- -------------
The client RPC wire protocol is defined and documented in ``net/corda/client/rpc/RPCApi.kt``. The client RPC wire protocol is defined and documented in ``net/corda/client/rpc/RPCApi.kt``.
Whitelisting classes with the Corda node Whitelisting classes with the Corda node
---------------------------------------- ----------------------------------------
CorDapps must whitelist any classes used over RPC with Corda's serialization framework, unless they are whitelisted by
To avoid the RPC interface being wide open to all default in ``DefaultWhitelist``. The whitelisting is done either via the plugin architecture or by using the
classes on the classpath, Cordapps have to whitelist any classes they require with the serialization framework of Corda, ``@CordaSerializable`` annotation. See :doc:`serialization`. An example is shown in :doc:`tutorial-clientrpc-api`.
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.
.. _CordaRPCClient: api/javadoc/net/corda/client/rpc/CordaRPCClient.html .. _CordaRPCClient: api/javadoc/net/corda/client/rpc/CordaRPCClient.html
.. _CordaRPCOps: api/javadoc/net/corda/core/messaging/CordaRPCOps.html .. _CordaRPCOps: api/javadoc/net/corda/core/messaging/CordaRPCOps.html

View File

@ -1,48 +1,12 @@
Deploying a node 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 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 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. 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, 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. debugging, and testing node configurations, but not for production or testnet deployment.

View File

@ -3,14 +3,12 @@ Running a node
Starting your node Starting your node
------------------ ------------------
After following the steps in :doc:`deploying-a-node`, you should have deployed your node(s) with any chosen CorDapps 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 .. code-block:: shell
Windows: java -jar corda.jar java -jar corda.jar
UNIX: ./corda.jar
.. warning:: If your working directory is not ``<node_dir>`` your plugins and configuration will not be used. .. 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 Debugging your node
------------------- -------------------
To enable remote debugging of the node, run the following from the terminal window: 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`` ``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. 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 .. 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`. 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 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``) * States (i.e. classes implementing ``ContractState``)
* Contracts (i.e. classes implementing ``Contract``) * 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 * Web APIs
* Services * Services
These files should be placed under ``src/main/[java|kotlin]``. The CorDapp's resources folder (``src/main/resources``) CorDapp structure
should also include the following subfolders: -----------------
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 The ``src`` directory of the Template CorDapp, where we define our CorDapp's source-code, has the following structure:
* ``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:
.. parsed-literal:: .. parsed-literal::
@ -59,87 +60,81 @@ structure:
└── contract └── contract
└── TemplateTests.java └── TemplateTests.java
Defining a plugin The build file
----------------- --------------
You can specify the transport options (between nodes and between Web Client and a node) for your CorDapp by subclassing At the root of the Template CorDapp, you will also find a ``build.gradle`` file. This file is useful for several
``net.corda.core.node.CordaPluginRegistry``: reasons:
* The ``customizeSerialization`` function allows classes to be whitelisted for object serialisation, over and Choosing your CorDapp version
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`. 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 .. sourcecode:: groovy
``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.
You can specify the web APIs and static web content for your CorDapp by implementing ext.corda_release_version = '0.13.0'
``net.corda.webserver.services.WebServerPluginRegistry`` interface: 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 In this case, our CorDapp will use the Milestone 13 release of Corda, and version 13.3 of the Corda gradle plugins. You
the bundled web server and must have a single argument constructor taking a ``CordaRPCOps`` object. This will can find the latest published version of both here: https://bintray.com/r3/corda.
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. ``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 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.