mirror of
https://github.com/corda/corda.git
synced 2024-12-23 14:52:29 +00:00
91d3ab3556
Signed-off-by: Ed Prosser <edward.prosser@r3.com>
471 lines
19 KiB
ReStructuredText
471 lines
19 KiB
ReStructuredText
Creating nodes locally
|
|
======================
|
|
|
|
.. contents::
|
|
|
|
Handcrafting a node
|
|
-------------------
|
|
A node can be created manually by creating a folder that contains the following items:
|
|
|
|
* The Corda JAR, downloaded from https://r3.bintray.com/corda/net/corda/corda/ (under /|corda_version|/corda-|corda_version|.jar)
|
|
* A node configuration file entitled ``node.conf``, configured as per :doc:`corda-configuration-file`
|
|
|
|
* A folder entitled ``cordapps`` containing any CorDapp JARs you want the node to load
|
|
|
|
* An up-to-date version of the ``network-parameters`` file ([see docs:](https://docs.corda.net/network-map.html#network-parameters)) generated by the bootstrapper tool
|
|
|
|
* **Optional:** A webserver JAR entitled ``corda-webserver-|corda_version|.jar`` that will connect to the node via RPC
|
|
|
|
* The (deprecated) default webserver is available to you for testing and should not be used in a production environment.
|
|
* A Spring Boot alternative can be found here: https://github.com/corda/spring-webserver
|
|
|
|
The remaining files and folders described in :doc:`node-structure` will be generated at runtime.
|
|
|
|
The Cordform task
|
|
-----------------
|
|
Corda provides a gradle plugin called ``Cordform`` that allows you to automatically generate and configure a set of
|
|
nodes for testing and demos. Here is an example ``Cordform`` task called ``deployNodes`` that creates three nodes, defined
|
|
in the `Kotlin CorDapp Template <https://github.com/corda/cordapp-template-kotlin/blob/release-V|platform_version|/build.gradle#L95>`_:
|
|
|
|
.. sourcecode:: groovy
|
|
|
|
task deployNodes(type: net.corda.plugins.Cordform, dependsOn: ['jar']) {
|
|
directory "./build/nodes"
|
|
node {
|
|
name "O=Notary,L=London,C=GB"
|
|
// The notary will offer a validating notary service.
|
|
notary = [validating : true]
|
|
p2pPort 10002
|
|
rpcSettings {
|
|
port 10003
|
|
adminPort 10023
|
|
}
|
|
// No webport property, so no webserver will be created.
|
|
h2Port 10004
|
|
// Starts an internal SSH server providing a management shell on the node.
|
|
sshdPort 2223
|
|
// Includes the corda-finance CorDapp on our node.
|
|
cordapps = ["$corda_release_distribution:corda-finance:$corda_release_version"]
|
|
extraConfig = [
|
|
// Setting the JMX reporter type.
|
|
jmxReporterType: 'JOLOKIA',
|
|
// Setting the H2 address.
|
|
h2Settings: [ address: 'localhost:10030' ]
|
|
]
|
|
}
|
|
node {
|
|
name "O=PartyA,L=London,C=GB"
|
|
p2pPort 10005
|
|
rpcSettings {
|
|
port 10006
|
|
adminPort 10026
|
|
}
|
|
webPort 10007
|
|
h2Port 10008
|
|
cordapps = ["$corda_release_distribution:corda-finance:$corda_release_version"]
|
|
// Grants user1 all RPC permissions.
|
|
rpcUsers = [[ user: "user1", "password": "test", "permissions": ["ALL"]]]
|
|
}
|
|
node {
|
|
name "O=PartyB,L=New York,C=US"
|
|
p2pPort 10009
|
|
rpcSettings {
|
|
port 10010
|
|
adminPort 10030
|
|
}
|
|
webPort 10011
|
|
h2Port 10012
|
|
cordapps = ["$corda_release_distribution:corda-finance:$corda_release_version"]
|
|
// Grants user1 the ability to start the MyFlow flow.
|
|
rpcUsers = [[ user: "user1", "password": "test", "permissions": ["StartFlow.net.corda.flows.MyFlow"]]]
|
|
}
|
|
}
|
|
|
|
Running this task will create three nodes in the ``build/nodes`` folder:
|
|
|
|
* A ``Notary`` node that:
|
|
|
|
* Offers a validating notary service
|
|
* Will not have a webserver (since ``webPort`` is not defined)
|
|
* Is running the ``corda-finance`` CorDapp
|
|
|
|
* ``PartyA`` and ``PartyB`` nodes that:
|
|
|
|
* Are not offering any services
|
|
* Will have a webserver (since ``webPort`` is defined)
|
|
* Are running the ``corda-finance`` CorDapp
|
|
* Have an RPC user, ``user1``, that can be used to log into the node via RPC
|
|
|
|
Additionally, all three nodes will include any CorDapps defined in the project's source folders, even though these
|
|
CorDapps are not listed in each node's ``cordapps`` entry. This means that running the ``deployNodes`` task from the
|
|
template CorDapp, for example, would automatically build and add the template CorDapp to each node.
|
|
|
|
The configuration values available in ``deployNodes`` task are as follows:
|
|
|
|
Required configuration
|
|
^^^^^^^^^^^^^^^^^^^^^^
|
|
|
|
* ``name`` <string>
|
|
|
|
* The legal identity name of the Corda node. (see :ref:`myLegalName <corda_configuration_file_myLegalName>`)
|
|
* e.g.
|
|
::
|
|
|
|
name "O=PartyA,L=London,C=GB"
|
|
|
|
* ``p2pAddress`` <string> <**required if p2pPort not specified**>
|
|
|
|
* The address/port the node uses for inbound communication from other nodes. (see :ref:`p2pAddress <corda_configuration_file_p2pAddress>`)
|
|
* e.g.
|
|
::
|
|
|
|
p2pAddress "example.com:10002"
|
|
|
|
* ``p2pPort`` <integer>
|
|
|
|
* The port the node uses for inbound communication from other nodes. Assumes the address is ``localhost``. (see :ref:`p2pAddress <corda_configuration_file_p2pAddress>`)
|
|
* e.g.
|
|
::
|
|
|
|
p2pPort 10006 // "localhost:10006"
|
|
|
|
* ``rpcSettings`` <config>
|
|
|
|
* Specifies RPC settings for the node. (see :ref:`rpcSettings <corda_configuration_file_rpc_settings>`)
|
|
* e.g.
|
|
::
|
|
|
|
rpcSettings {
|
|
port 10006
|
|
adminPort 10026
|
|
}
|
|
|
|
Optional configuration
|
|
^^^^^^^^^^^^^^^^^^^^^^
|
|
|
|
* ``notary`` <config> (see :ref:`notary <corda_configuration_file_notary>`)
|
|
|
|
* Optional configuration which specifies the node is a notary.
|
|
* .. note:: <**required**> for notary nodes
|
|
|
|
* ``devMode`` <boolean>
|
|
|
|
* When true enables development mode. (see :ref:`devMode <corda_configuration_file_dev_mode>`)
|
|
* e.g.
|
|
::
|
|
|
|
devMode true
|
|
|
|
* ``webAddress`` <string>
|
|
|
|
* Configure a webserver to connect to the node via RPC. This will specify the address and port it will listen on. The node must have an RPC address configured. (see :ref:`Specifying a custom webserver<specify-custom-webserver>`)
|
|
* e.g.
|
|
::
|
|
|
|
webAddress "example.com:10011"
|
|
|
|
* ``webPort`` <integer>
|
|
|
|
* Configure a webserver to connect to the node via RPC. Defaults the address to `localhost`. The node must have an RPC address configured. (see :ref:`Specifying a custom webserver<specify-custom-webserver>`)
|
|
* e.g.
|
|
::
|
|
|
|
webPort 10011 // "localhost:10011"
|
|
|
|
* ``rpcUsers`` <list>
|
|
|
|
* Set the RPC users for this node. (see :ref:`rpcUsers <corda_configuration_file_rpc_users>`)
|
|
* e.g.
|
|
::
|
|
|
|
rpcUsers = [[ user: "user1", "password": "test", "permissions": ["StartFlow.net.corda.flows.MyFlow"]]]
|
|
|
|
* This configuration block allows arbitrary configuration. Incorrect configurations will not cause a DSL error.
|
|
|
|
* ``configFile`` <string>
|
|
|
|
* For extending configuration of nodes. (see :ref:`extended node configuration <generating_a_node_extended_config>`)
|
|
* e.g.
|
|
::
|
|
|
|
configFile = "samples/trader-demo/src/main/resources/node-b.conf"
|
|
|
|
* ``https`` <boolean>
|
|
|
|
* When true enables HTTPS communication from the node webserver.
|
|
* e.g.
|
|
::
|
|
|
|
https true
|
|
|
|
* ``sshdPort`` <integer>
|
|
|
|
* Specifies the port for sshd communication. (see :ref:`sshd <corda_configuration_file_sshd>`)
|
|
* e.g.
|
|
::
|
|
|
|
sshd {
|
|
port = 2222
|
|
}
|
|
|
|
You can extend the task ``deployNodes`` with more ``node {}`` blocks to generate as many nodes as necessary for your application.
|
|
|
|
.. warning:: When adding nodes, make sure that there are no port clashes!
|
|
|
|
.. _generating_a_node_extended_config:
|
|
|
|
To extend node configuration beyond the properties defined in the ``deployNodes`` task use the ``configFile`` property with the path (relative or absolute) set to an additional configuration file.
|
|
This file should follow the standard :doc:`corda-configuration-file` format, as per node.conf. The properties from this file will be appended to the generated node configuration. Note, if you add a property already created by the 'deployNodes' task, both properties will be present in the file.
|
|
The path to the file can also be added while running the Gradle task via the ``-PconfigFile`` command line option. However, the same file will be applied to all nodes.
|
|
Following the previous example ``PartyB`` node will have additional configuration options added from a file ``none-b.conf``:
|
|
|
|
.. sourcecode:: groovy
|
|
|
|
task deployNodes(type: net.corda.plugins.Cordform, dependsOn: ['jar']) {
|
|
[...]
|
|
node {
|
|
name "O=PartyB,L=New York,C=US"
|
|
[...]
|
|
// Grants user1 the ability to start the MyFlow flow.
|
|
rpcUsers = [[ user: "user1", "password": "test", "permissions": ["StartFlow.net.corda.flows.MyFlow"]]]
|
|
configFile = "samples/trader-demo/src/main/resources/node-b.conf"
|
|
}
|
|
}
|
|
|
|
Cordform parameter `drivers` of the `node` entry lists paths of the files to be copied to the `./drivers` subdirectory of the node.
|
|
To copy the same file to all nodes `ext.drivers` can be defined in the top level and reused for each node via `drivers=ext.drivers``.
|
|
|
|
.. sourcecode:: groovy
|
|
|
|
task deployNodes(type: net.corda.plugins.Cordform, dependsOn: ['jar']) {
|
|
ext.drivers = ['lib/my_common_jar.jar']
|
|
[...]
|
|
node {
|
|
name "O=PartyB,L=New York,C=US"
|
|
[...]
|
|
drivers = ext.drivers + ['lib/my_specific_jar.jar']
|
|
}
|
|
}
|
|
|
|
.. _node_package_namespace_ownership:
|
|
|
|
Package namespace ownership
|
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
To specify :doc:`design/data-model-upgrades/package-namespace-ownership` configuration, the optional ``networkParameterOverrides`` and ``packageOwnership`` blocks can be used, similar to the configuration file used in :doc:`network-bootstrapper`:
|
|
|
|
.. sourcecode:: groovy
|
|
|
|
task deployNodes(type: net.corda.plugins.Cordform, dependsOn: ['jar']) {
|
|
[...]
|
|
networkParameterOverrides {
|
|
packageOwnership {
|
|
"com.mypackagename" {
|
|
keystore = "_teststore"
|
|
keystorePassword = "MyStorePassword"
|
|
keystoreAlias = "MyKeyAlias"
|
|
}
|
|
}
|
|
}
|
|
[...]
|
|
}
|
|
|
|
|
|
Signing CorDapp JARs
|
|
^^^^^^^^^^^^^^^^^^^^
|
|
The default behaviour of Cordform is to deploy CorDapp JARs "as built":
|
|
|
|
- prior to Corda 4 all CorDapp JARs were unsigned.
|
|
- as of Corda 4, CorDapp JARs created by the Gradle *cordapp* plugin are signed by a Corda development certificate by default.
|
|
|
|
The Cordform ``signing`` entry can be used to override and customise the signing of CorDapp JARs.
|
|
Signing the CorDapp enables its contract classes to use signature constraints instead of other types of the constraints :doc:`api-contract-constraints`.
|
|
|
|
The sign task may use an external keystore, or create a new one.
|
|
The ``signing`` entry may contain the following parameters:
|
|
|
|
* ``enabled`` the control flag to enable signing process, by default is set to ``false``, set to ``true`` to enable signing
|
|
* ``all`` if set to ``true`` (by default) all CorDapps inside *cordapp* subdirectory will be signed, otherwise if ``false`` then only the generated Cordapp will be signed
|
|
* ``options`` any relevant parameters of `SignJar ANT task <https://ant.apache.org/manual/Tasks/signjar.html>`_ and `GenKey ANT task <https://ant.apache.org/manual/Tasks/genkey.html>`_,
|
|
by default the JAR file is signed by Corda development key, the external keystore can be specified,
|
|
the minimal list of required options is shown below, for other options referer to `SignJar task <https://ant.apache.org/manual/Tasks/signjar.html>`_:
|
|
|
|
* ``keystore`` the path to the keystore file, by default *cordadevcakeys.jks* keystore is shipped with the plugin
|
|
* ``alias`` the alias to sign under, the default value is *cordaintermediateca*
|
|
* ``storepass`` the keystore password, the default value is *cordacadevpass*
|
|
* ``keypass`` the private key password if it's different than the password for the keystore, the default value is *cordacadevkeypass*
|
|
* ``storetype`` the keystore type, the default value is *JKS*
|
|
* ``dname`` the distinguished name for entity, the option is used when ``generateKeystore true`` only
|
|
* ``keyalg`` the method to use when generating name-value pair, the value defaults to *RSA* as Corda doesn't support *DSA*, the option is used when ``generateKeystore true`` only
|
|
|
|
* ``generateKeystore`` the flag to generate a keystore, it is set to ``false`` by default. If set to ``true`` then ad hock keystore is created and its key isused
|
|
instead of the default Corda development key or any external key.
|
|
The same ``options`` to specify an external keystore are used to define the newly created keystore. Additionally
|
|
``dname`` and ``keyalg`` are required. Other options are described in `GenKey task <https://ant.apache.org/manual/Tasks/genkey.html>`_.
|
|
If the existing keystore is already present the task will reuse it, however if the file is inside the *build* directory,
|
|
then it will be deleted when Gradle *clean* task is run.
|
|
|
|
The example below shows the minimal set of ``options`` needed to create a dummy keystore:
|
|
|
|
.. sourcecode:: groovy
|
|
|
|
task deployNodes(type: net.corda.plugins.Cordform, dependsOn: ['jar']) {
|
|
signing {
|
|
enabled true
|
|
generateKeystore true
|
|
all false
|
|
options {
|
|
keystore "./build/nodes/jarSignKeystore.p12"
|
|
alias "cordapp-signer"
|
|
storepass "secret1!"
|
|
storetype "PKCS12"
|
|
dname "OU=Dummy Cordapp Distributor, O=Corda, L=London, C=GB"
|
|
keyalg "RSA"
|
|
}
|
|
}
|
|
//...
|
|
|
|
Contracts classes from signed CorDapp JARs will be checked by signature constraints by default.
|
|
You can force them to be checked by zone constraints by adding contract class names to ``includeWhitelist`` entry,
|
|
the list will generate *include_whitelist.txt* file used internally by :doc:`network-bootstrapper` tool.
|
|
Refer to :doc:`api-contract-constraints` to understand implication of different constraint types before adding ``includeWhitelist`` to ``deployNodes`` task.
|
|
The snippet below configures contracts classes from Finance CorDapp to be verified using zone constraints instead of signature constraints:
|
|
|
|
.. sourcecode:: groovy
|
|
|
|
task deployNodes(type: net.corda.plugins.Cordform, dependsOn: ['jar']) {
|
|
includeWhitelist = [ "net.corda.finance.contracts.asset.Cash", "net.corda.finance.contracts.asset.CommercialPaper" ]
|
|
//...
|
|
|
|
.. _specify-custom-webserver:
|
|
|
|
Specifying a custom webserver
|
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
By default, any node listing a web port will use the default development webserver, which is not production-ready. You
|
|
can use your own webserver JAR instead by using the ``webserverJar`` argument in a ``Cordform`` ``node`` configuration
|
|
block:
|
|
|
|
.. sourcecode:: groovy
|
|
|
|
node {
|
|
name "O=PartyA,L=New York,C=US"
|
|
webPort 10005
|
|
webserverJar "lib/my_webserver.jar"
|
|
}
|
|
|
|
The webserver JAR will be copied into the node's ``build`` folder with the name ``corda-webserver.jar``.
|
|
|
|
.. warning:: This is an experimental feature. There is currently no support for reading the webserver's port from the
|
|
node's ``node.conf`` file.
|
|
|
|
The Dockerform task
|
|
-------------------
|
|
|
|
The ``Dockerform`` is a sister task of ``Cordform`` that provides an extra file allowing you to easily spin up nodes using ``docker-compose``. It supports the following configuration options for each node:
|
|
|
|
* ``name``
|
|
* ``notary``
|
|
* ``cordapps``
|
|
* ``rpcUsers``
|
|
* ``useTestClock``
|
|
|
|
|
|
The nodes' webservers will not be started. Instead, you should interact with each node via its shell over SSH
|
|
(see the :doc:`node configuration options <corda-configuration-file>`). You have to enable the shell by adding the
|
|
following line to each node's ``node.conf`` file:
|
|
|
|
``sshd { port = <NUMBER> }``
|
|
|
|
Where ``<NUMBER>`` is the port you want to open to SSH into the shell.
|
|
|
|
To run the Dockerform task, follow these steps:
|
|
|
|
1. Run ``./gradlew deployNodes`` to generate the node files and folder structure.
|
|
|
|
2. Open the ``build.gradle`` file and add a new ``dockerform`` task after the existing ``deployNodes`` task:
|
|
|
|
.. sourcecode:: groovy
|
|
|
|
task prepareDockerNodes(type: net.corda.plugins.Dockerform, dependsOn: ['jar']) {
|
|
nodeDefaults {
|
|
cordapp project(":contracts-java")
|
|
}
|
|
node {
|
|
name "O=Notary,L=London,C=GB"
|
|
notary = [validating : false]
|
|
p2pPort 10002
|
|
rpcSettings {
|
|
address("localhost:10003")
|
|
adminAddress("localhost:10023")
|
|
}
|
|
projectCordapp {
|
|
deploy = false
|
|
}
|
|
cordapps.clear()
|
|
}
|
|
node {
|
|
name "O=PartyA,L=London,C=GB"
|
|
p2pPort 10002
|
|
rpcSettings {
|
|
address("localhost:10003")
|
|
adminAddress("localhost:10023")
|
|
}
|
|
rpcUsers = [[user: "user1", "password": "test", "permissions": ["ALL"]]]
|
|
}
|
|
node {
|
|
name "O=PartyB,L=New York,C=US"
|
|
p2pPort 10002
|
|
rpcSettings {
|
|
address("localhost:10003")
|
|
adminAddress("localhost:10023")
|
|
}
|
|
rpcUsers = [[user: "user1", "password": "test", "permissions": ["ALL"]]]
|
|
}
|
|
}
|
|
|
|
3. Create an empty ``docker-compose.yml`` file using the following command on Mac or Linux:
|
|
|
|
``touch workflows-java/build/nodes/docker-compose.yml``
|
|
|
|
For Windows, use the following command:
|
|
|
|
``echo.> workflows-java\build\nodes\docker-compose.yml``
|
|
|
|
4. Run ``./gradlew prepareDockerNodes`` and edit the generated ``docker-compose.yml`` file to change the ports:
|
|
|
|
.. sourcecode:: groovy
|
|
|
|
version: '3'
|
|
services:
|
|
notary:
|
|
build: /Users/<USER>/Projects/json-cordapp/workflows-java/build/nodes/Notary
|
|
ports:
|
|
- "10002"
|
|
- "10003"
|
|
partya:
|
|
build: /Users/<USER>/Projects/json-cordapp/workflows-java/build/nodes/PartyA
|
|
ports:
|
|
- "10002"
|
|
- "10003"
|
|
partyb:
|
|
build: /Users/<USER>/Projects/json-cordapp/workflows-java/build/nodes/PartyB
|
|
ports:
|
|
- "10002"
|
|
- "10003"
|
|
|
|
|
|
Running the Cordform/Dockerform tasks
|
|
-------------------------------------
|
|
To create the nodes defined in our ``deployNodes`` task, run the following command in a terminal window from the root
|
|
of the project where the ``deployNodes`` task is defined:
|
|
|
|
* Linux/macOS: ``./gradlew deployNodes``
|
|
* Windows: ``gradlew.bat deployNodes``
|
|
|
|
This will create the nodes in the ``build/nodes`` folder. There will be a node folder generated for each node defined
|
|
in the ``deployNodes`` task, plus a ``runnodes`` shell script (or batch file on Windows) to run all the nodes at once
|
|
for testing and development purposes. If you make any changes to your CorDapp source or ``deployNodes`` task, you will
|
|
need to re-run the task to see the changes take effect.
|
|
|
|
If the task is a ``Dockerform`` task, running the task will also create an additional ``Dockerfile`` in each node
|
|
directory in the ``build/nodes`` directory.
|