2016-10-04 12:56:31 +00:00
|
|
|
.. _graphstream: http://graphstream-project.org/
|
|
|
|
|
2016-11-25 14:29:13 +00:00
|
|
|
Client RPC API tutorial
|
2016-11-15 12:36:17 +00:00
|
|
|
=======================
|
2016-10-04 12:56:31 +00:00
|
|
|
|
2017-05-10 10:28:25 +00:00
|
|
|
In this tutorial we will build a simple command line utility that connects to a node, creates some Cash transactions and
|
|
|
|
meanwhile dumps the transaction graph to the standard output. We will then put some simple visualisation on top. For an
|
|
|
|
explanation on how the RPC works see :doc:`clientrpc`.
|
2016-10-04 12:56:31 +00:00
|
|
|
|
2017-05-10 10:28:25 +00:00
|
|
|
We start off by connecting to the node itself. For the purposes of the tutorial we will use the Driver to start up a notary
|
|
|
|
and a node that issues/exits and moves Cash around for herself. To authenticate we will use the certificates of the nodes
|
|
|
|
directly.
|
2016-10-04 12:56:31 +00:00
|
|
|
|
2016-11-22 16:30:17 +00:00
|
|
|
Note how we configure the node to create a user that has permission to start the CashFlow.
|
2016-11-15 12:36:17 +00:00
|
|
|
|
|
|
|
.. literalinclude:: example-code/src/main/kotlin/net/corda/docs/ClientRpcTutorial.kt
|
2016-10-04 12:56:31 +00:00
|
|
|
:language: kotlin
|
|
|
|
:start-after: START 1
|
|
|
|
:end-before: END 1
|
|
|
|
|
2016-11-15 12:36:17 +00:00
|
|
|
Now we can connect to the node itself using a valid RPC login. We login using the configured user.
|
2016-10-04 12:56:31 +00:00
|
|
|
|
2016-11-15 12:36:17 +00:00
|
|
|
.. literalinclude:: example-code/src/main/kotlin/net/corda/docs/ClientRpcTutorial.kt
|
2016-10-04 12:56:31 +00:00
|
|
|
:language: kotlin
|
|
|
|
:start-after: START 2
|
|
|
|
:end-before: END 2
|
|
|
|
|
2017-05-10 10:28:25 +00:00
|
|
|
We start generating transactions in a different thread (``generateTransactions`` to be defined later) using ``proxy``,
|
|
|
|
which exposes the full RPC interface of the node:
|
2016-10-04 12:56:31 +00:00
|
|
|
|
2017-05-03 10:02:56 +00:00
|
|
|
.. literalinclude:: ../../core/src/main/kotlin/net/corda/core/messaging/CordaRPCOps.kt
|
2016-10-04 12:56:31 +00:00
|
|
|
:language: kotlin
|
|
|
|
:start-after: interface CordaRPCOps
|
|
|
|
:end-before: }
|
|
|
|
|
2017-05-10 10:28:25 +00:00
|
|
|
.. warning:: This API is evolving and will continue to grow as new functionality and features added to Corda are made
|
|
|
|
available to RPC clients.
|
2016-11-25 17:56:56 +00:00
|
|
|
|
2016-10-04 12:56:31 +00:00
|
|
|
The one we need in order to dump the transaction graph is ``verifiedTransactions``. The type signature tells us that the
|
|
|
|
RPC will return a list of transactions and an Observable stream. This is a general pattern, we query some data and the
|
2016-11-25 17:56:56 +00:00
|
|
|
node will return the current snapshot and future updates done to it. Observables are described in further detail in
|
|
|
|
:doc:`clientrpc`
|
2016-10-04 12:56:31 +00:00
|
|
|
|
2016-11-15 12:36:17 +00:00
|
|
|
.. literalinclude:: example-code/src/main/kotlin/net/corda/docs/ClientRpcTutorial.kt
|
2016-10-04 12:56:31 +00:00
|
|
|
:language: kotlin
|
|
|
|
:start-after: START 3
|
|
|
|
:end-before: END 3
|
|
|
|
|
|
|
|
The graph will be defined by nodes and edges between them. Each node represents a transaction and edges represent
|
|
|
|
output-input relations. For now let's just print ``NODE <txhash>`` for the former and ``EDGE <txhash> <txhash>`` for the
|
|
|
|
latter.
|
|
|
|
|
2016-11-15 12:36:17 +00:00
|
|
|
.. literalinclude:: example-code/src/main/kotlin/net/corda/docs/ClientRpcTutorial.kt
|
2016-10-04 12:56:31 +00:00
|
|
|
:language: kotlin
|
|
|
|
:start-after: START 4
|
|
|
|
:end-before: END 4
|
|
|
|
|
|
|
|
|
2016-11-15 12:36:17 +00:00
|
|
|
Now we just need to create the transactions themselves!
|
2016-10-04 12:56:31 +00:00
|
|
|
|
2016-11-15 12:36:17 +00:00
|
|
|
.. literalinclude:: example-code/src/main/kotlin/net/corda/docs/ClientRpcTutorial.kt
|
|
|
|
:language: kotlin
|
|
|
|
:start-after: START 6
|
|
|
|
:end-before: END 6
|
2016-10-04 12:56:31 +00:00
|
|
|
|
2017-05-10 10:28:25 +00:00
|
|
|
We utilise several RPC functions here to query things like the notaries in the node cluster or our own vault. These RPC
|
|
|
|
functions also return ``Observable`` objects so that the node can send us updated values. However, we don't need updates
|
|
|
|
here and so we mark these observables as ``notUsed``. (As a rule, you should always either subscribe to an ``Observable``
|
|
|
|
or mark it as not used. Failing to do this will leak resources in the node.)
|
2016-10-04 12:56:31 +00:00
|
|
|
|
2016-11-15 12:36:17 +00:00
|
|
|
Then in a loop we generate randomly either an Issue, a Pay or an Exit transaction.
|
2016-10-04 12:56:31 +00:00
|
|
|
|
2017-05-10 10:28:25 +00:00
|
|
|
The RPC we need to initiate a Cash transaction is ``startFlowDynamic`` which may start an arbitrary flow, given sufficient
|
|
|
|
permissions to do so. We won't use this function directly, but rather a type-safe wrapper around it ``startFlow`` that
|
|
|
|
type-checks the arguments for us.
|
2016-10-04 12:56:31 +00:00
|
|
|
|
2017-05-10 10:28:25 +00:00
|
|
|
Finally we have everything in place: we start a couple of nodes, connect to them, and start creating transactions while
|
|
|
|
listening on successfully created ones, which are dumped to the console. We just need to run it!:
|
2016-10-04 12:56:31 +00:00
|
|
|
|
2016-11-28 10:12:23 +00:00
|
|
|
.. code-block:: text
|
2016-11-21 16:39:46 +00:00
|
|
|
|
2016-11-15 12:36:17 +00:00
|
|
|
# Build the example
|
|
|
|
./gradlew docs/source/example-code:installDist
|
|
|
|
# Start it
|
|
|
|
./docs/source/example-code/build/install/docs/source/example-code/bin/client-rpc-tutorial Print
|
2016-10-04 12:56:31 +00:00
|
|
|
|
|
|
|
Now let's try to visualise the transaction graph. We will use a graph drawing library called graphstream_
|
|
|
|
|
2016-11-15 12:36:17 +00:00
|
|
|
.. literalinclude:: example-code/src/main/kotlin/net/corda/docs/ClientRpcTutorial.kt
|
2016-10-04 12:56:31 +00:00
|
|
|
:language: kotlin
|
|
|
|
:start-after: START 5
|
|
|
|
:end-before: END 5
|
|
|
|
|
2016-11-15 12:36:17 +00:00
|
|
|
If we run the client with ``Visualise`` we should see a simple random graph being drawn as new transactions are being created.
|
2016-11-15 17:16:33 +00:00
|
|
|
|
2017-02-28 08:12:18 +00:00
|
|
|
Whitelisting classes from your CorDapp with the Corda node
|
|
|
|
----------------------------------------------------------
|
2016-11-15 17:16:33 +00:00
|
|
|
|
2017-02-28 08:12:18 +00:00
|
|
|
As described in :doc:`clientrpc`, you have to whitelist any additional classes you add that are needed in RPC
|
|
|
|
requests or responses with the Corda node. Here's an example of both ways you can do this for a couple of example classes.
|
2016-11-15 17:16:33 +00:00
|
|
|
|
|
|
|
.. literalinclude:: example-code/src/main/kotlin/net/corda/docs/ClientRpcTutorial.kt
|
|
|
|
:language: kotlin
|
|
|
|
:start-after: START 7
|
|
|
|
:end-before: END 7
|
|
|
|
|
|
|
|
See more on plugins in :doc:`creating-a-cordapp`.
|
|
|
|
|
2017-02-28 08:12:18 +00:00
|
|
|
.. warning:: We will be replacing the use of Kryo in the serialization framework and so additional changes here are likely.
|
2016-11-25 17:56:56 +00:00
|
|
|
|
|
|
|
Security
|
|
|
|
--------
|
|
|
|
RPC credentials associated with a Client must match the permission set configured on the server Node.
|
2016-11-29 09:41:50 +00:00
|
|
|
This refers to both authentication (username and password) and role-based authorisation (a permissioned set of RPC operations an
|
2016-11-25 17:56:56 +00:00
|
|
|
authenticated user is entitled to run).
|
|
|
|
|
2017-05-10 10:28:25 +00:00
|
|
|
.. note:: Permissions are represented as *String's* to allow RPC implementations to add their own permissioning. Currently
|
|
|
|
the only permission type defined is *StartFlow*, which defines a list of whitelisted flows an authenticated use may
|
|
|
|
execute. An administrator user (or a developer) may also be assigned the ``ALL`` permission, which grants access to
|
|
|
|
any flow.
|
2016-11-29 09:41:50 +00:00
|
|
|
|
2016-11-25 17:56:56 +00:00
|
|
|
In the instructions above the server node permissions are configured programmatically in the driver code:
|
|
|
|
|
|
|
|
.. code-block:: text
|
|
|
|
|
|
|
|
driver(driverDirectory = baseDirectory) {
|
2016-11-29 09:41:50 +00:00
|
|
|
val user = User("user", "password", permissions = setOf(startFlowPermission<CashFlow>()))
|
2017-04-13 16:41:54 +00:00
|
|
|
val node = startNode("CN=Alice Corp,O=Alice Corp,L=London,C=UK", rpcUsers = listOf(user)).get()
|
2016-11-25 17:56:56 +00:00
|
|
|
|
|
|
|
When starting a standalone node using a configuration file we must supply the RPC credentials as follows:
|
|
|
|
|
|
|
|
.. code-block:: text
|
|
|
|
|
|
|
|
rpcUsers : [
|
2017-04-07 10:23:25 +00:00
|
|
|
{ username=user, password=password, permissions=[ StartFlow.net.corda.flows.CashFlow ] }
|
2016-11-25 17:56:56 +00:00
|
|
|
]
|
|
|
|
|
2017-05-10 10:28:25 +00:00
|
|
|
When using the gradle Cordformation plugin to configure and deploy a node you must supply the RPC credentials in a similar
|
|
|
|
manner:
|
2016-11-25 17:56:56 +00:00
|
|
|
|
|
|
|
.. code-block:: text
|
|
|
|
|
|
|
|
rpcUsers = [
|
2017-04-07 10:23:25 +00:00
|
|
|
['username' : "user",
|
2016-11-25 17:56:56 +00:00
|
|
|
'password' : "password",
|
|
|
|
'permissions' : ["StartFlow.net.corda.flows.CashFlow"]]
|
|
|
|
]
|
|
|
|
|
|
|
|
You can then deploy and launch the nodes (Notary and Alice) as follows:
|
|
|
|
|
2016-11-28 10:12:23 +00:00
|
|
|
.. code-block:: text
|
2016-11-25 17:56:56 +00:00
|
|
|
|
2016-11-28 10:12:23 +00:00
|
|
|
# to create a set of configs and installs under ``docs/source/example-code/build/nodes`` run
|
|
|
|
./gradlew docs/source/example-code:deployNodes
|
|
|
|
# to open up two new terminals with the two nodes run
|
|
|
|
./docs/source/example-code/build/nodes/runnodes
|
|
|
|
# followed by the same commands as before:
|
|
|
|
./docs/source/example-code/build/install/docs/source/example-code/bin/client-rpc-tutorial Print
|
|
|
|
./docs/source/example-code/build/install/docs/source/example-code/bin/client-rpc-tutorial Visualise
|
2016-11-25 17:56:56 +00:00
|
|
|
|
2017-05-10 10:28:25 +00:00
|
|
|
With regards to the start flow RPCs, there is an extra layer of security whereby the flow to be executed has to be
|
|
|
|
annotated with ``@StartableByRPC``. Flows without this annotation cannot execute using RPC.
|
|
|
|
|
2016-11-29 18:42:23 +00:00
|
|
|
See more on security in :doc:`secure-coding-guidelines`, node configuration in :doc:`corda-configuration-file` and
|
2016-11-28 10:12:23 +00:00
|
|
|
Cordformation in :doc:`creating-a-cordapp`
|