mirror of
https://github.com/corda/corda.git
synced 2025-01-20 03:36:29 +00:00
Adds information on writing CorDapps. Reorg.
This commit is contained in:
parent
407b467f67
commit
5eb8b36809
@ -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
|
||||
|
@ -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.
|
||||
|
||||
|
@ -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
|
@ -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.
|
||||
|
@ -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.
|
||||
|
Loading…
Reference in New Issue
Block a user