Reflects V1.0 changes on Master re: internal samples and identity sync flow API.

This commit is contained in:
Joel Dudley 2017-10-25 09:29:32 +01:00 committed by GitHub
parent 5349d4f850
commit 5bb4601812
10 changed files with 270 additions and 586 deletions

View File

@ -7,61 +7,59 @@ API: Identity
Party
-----
Identities on the network are represented by ``AbstractParty``. There are two types of ``AbstractParty``:
Parties on the network are represented using the ``AbstractParty`` class. There are two types of ``AbstractParty``:
* ``Party``, identified by a ``PublicKey`` and a ``CordaX500Name``
* ``AnonymousParty``, identified by a ``PublicKey`` only
* ``AnonymousParty``, identified by a ``PublicKey``
Using ``AnonymousParty`` to identify parties in states and commands prevents nodes from learning the identities
of the parties involved in a transaction when they verify the transaction's dependency chain. When preserving the
anonymity of each party is not required (e.g. for internal processing), ``Party`` can be used instead.
For example, in a transaction sent to your node as part of a chain of custody it is important you can convince yourself
of the transaction's validity, but equally important that you don't learn anything about who was involved in that
transaction. In these cases ``AnonymousParty`` should be used by flows constructing when transaction states and commands.
In contrast, for internal processing where extended details of a party are required, the ``Party`` class should be used
instead. The identity service provides functionality for flows to resolve anonymous parties to full parties, dependent
on the anonymous party's identity having been registered with the node earlier (typically this is handled by
``SwapIdentitiesFlow`` or ``IdentitySyncFlow``, discussed below).
The identity service allows flows to resolve ``AnonymousParty`` to ``Party``, but only if the anonymous party's
identity has already been registered with the node (typically handled by ``SwapIdentitiesFlow`` or
``IdentitySyncFlow``, discussed below).
Party names are held within the ``CordaX500Name`` data class, which enforces the structure of names within Corda, as
well as ensuring a consistent rendering of the names in plain text.
Party names use the ``CordaX500Name`` data class, which enforces the structure of names within Corda, as well as
ensuring a consistent rendering of the names in plain text.
The support for both Party and AnonymousParty classes in Corda enables sophisticated selective disclosure of identity
information. For example, it is possible to construct a Transaction using an AnonymousParty, so nobody can learn of your
involvement by inspection of the transaction, yet prove to specific counterparts that this AnonymousParty actually is
owned by your well known identity. This disclosure is achieved through the use of the PartyAndCertificate data class
which can be propagated to those who need to know, and contains the Party's X.509 certificate path to provide proof of
ownership by a well known identity.
Support for both ``Party`` and ``AnonymousParty`` classes in Corda enables sophisticated selective disclosure of
identity information. For example, it is possible to construct a transaction using an ``AnonymousParty`` (so nobody can
learn of your involvement by inspection of the transaction), yet prove to specific counterparts that this
``AnonymousParty`` actually corresponds to your well-known identity. This is achieved using the
``PartyAndCertificate`` data class, which contains the X.509 certificate path proving that a given ``AnonymousParty``
corresponds to a given ``Party``. Each ``PartyAndCertificate`` can be propagated to counterparties on a need-to-know
basis.
The PartyAndCertificate class is also used in the network map service to represent well known identities, in which
scenario the certificate path proves its issuance by the Doorman service.
The ``PartyAndCertificate`` class is also used by the network map service to represent well-known identities, with the
certificate path proving the certificate was issued by the doorman service.
Confidential Identities
Confidential identities
-----------------------
Confidential identities are key pairs where the corresponding X.509 certificate (and path) are not made public, so that parties who
are not involved in the transaction cannot identify its participants. They are owned by a well known identity, which
must sign the X.509 certificate. Before constructing a new transaction the involved parties must generate and send new
confidential identities to each other, a process which is managed using ``SwapIdentitiesFlow`` (discussed below). The
public keys of these confidential identities are then used when generating output states and commands for the transaction.
Confidential identities are key pairs where the corresponding X.509 certificate (and path) are not made public, so that
parties who are not involved in the transaction cannot identify the owner. They are owned by a well-known identity,
which must sign the X.509 certificate. Before constructing a new transaction the involved parties must generate and
exchange new confidential identities, a process which is managed using ``SwapIdentitiesFlow`` (discussed below). The
public keys of these confidential identities are then used when generating output states and commands for the
transaction.
Where using outputs from a previous transaction in a new transaction, counterparties may need to know who the involved
parties are. One example is in ``TwoPartyTradeFlow`` which delegates to ``CollectSignaturesFlow`` to gather certificates
from both parties. ``CollectSignaturesFlow`` requires that a confidential identity of the initiating node has signed
the transaction, and verifying this requires the receiving node has a copy of the confidential identity for the input
state. ``IdentitySyncFlow`` can be used to synchronize the confidential identities we have the certificate paths for, in
a single transaction, to another node.
parties are. One example is the ``TwoPartyTradeFlow``, where an existing asset is exchanged for cash. If confidential
identities are being used, the buyer will want to ensure that the asset being transferred is owned by the seller, and
the seller will likewise want to ensure that the cash being transferred is owned by the buyer. Verifying this requires
both nodes to have a copy of the confidential identities for the asset and cash input states. ``IdentitySyncFlow``
manages this process. It takes as inputs a transaction and a counterparty, and for every confidential identity involved
in that transaction for which the calling node holds the certificate path, it sends this certificate path to the
counterparty.
.. note:: ``CollectSignaturesFlow`` requires that the initiating node has signed the transaction, and as such all nodes
providing signatures must recognise the signing key used by the initiating node as being either its well known identity
or a confidential identity they have the certificate for.
SwapIdentitiesFlow
~~~~~~~~~~~~~~~~~~
``SwapIdentitiesFlow`` is typically run as a subflow of another flow. It takes as its sole constructor argument the
counterparty we want to exchange confidential identities with. It returns a mapping from the identities of the caller
and the counterparty to their new confidential identities. In the future, this flow will be extended to handle swapping
identities with multiple parties at once.
Swap identities flow
~~~~~~~~~~~~~~~~~~~~
``SwapIdentitiesFlow`` takes the party to swap identities with in its constructor (the counterparty), and is typically run as a subflow of
another flow. It returns a mapping from well known identities of the calling flow and our counterparty to the new
confidential identities; in future this will be extended to handle swapping identities with multiple parties.
You can see an example of it being used in ``TwoPartyDealFlow.kt``:
You can see an example of using ``SwapIdentitiesFlow`` in ``TwoPartyDealFlow.kt``:
.. container:: codeset
@ -71,30 +69,35 @@ You can see an example of it being used in ``TwoPartyDealFlow.kt``:
:end-before: DOCEND 2
:dedent: 8
The swap identities flow goes through the following key steps:
``SwapIdentitiesFlow`` goes through the following key steps:
1. Generate a nonce value to form a challenge to the other nodes.
2. Send nonce value to all counterparties, and receive their nonce values.
3. Generate a new confidential identity from our well known identity.
1. Generate a nonce value to form a challenge to the other nodes
2. Send nonce value to all counterparties, and receive their nonce values
3. Generate a new confidential identity from our well-known identity
4. Create a data blob containing the new confidential identity (public key, name and X.509 certificate path),
and the hash of the nonce values.
5. Sign the resulting data blob with the confidential identity's private key.
6. Send the confidential identity and data blob signature to all counterparties, while receiving theirs.
7. Verify the signatures to ensure that identities were generated by the involved set of parties.
8. Verify the confidential identities are owned by the expected well known identities.
9. Store the confidential identities and return them to the calling flow.
and the hash of the nonce values
5. Sign the resulting data blob with the confidential identity's private key
6. Send the confidential identity and data blob signature to all counterparties, while receiving theirs
7. Verify the signatures to ensure that identities were generated by the involved set of parties
8. Verify the confidential identities are owned by the expected well known identities
9. Store the confidential identities and return them to the calling flow
This ensures not only that the confidential identity X.509 certificates are signed by the correct well known identities,
but also that the confidential identity private key is held by the counterparty, and that a party cannot claim ownership
another party's confidential identities belong to its well known identity.
This ensures not only that the confidential identity X.509 certificates are signed by the correct well-known
identities, but also that the confidential identity private key is held by the counterparty, and that a party cannot
claim ownership of another party's confidential identities.
Identity synchronization flow
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
IdentitySyncFlow
~~~~~~~~~~~~~~~~
When constructing a transaction whose input states reference confidential identities, it is common for counterparties
to require knowledge of which well-known identity each confidential identity maps to. ``IdentitySyncFlow`` handles this
process. You can see an example of its use in ``TwoPartyTradeFlow.kt``.
When constructing a transaction whose input states reference confidential identities, it is common for other signing
entities (counterparties) to require to know which well known identities those confidential identities map to. The
``IdentitySyncFlow`` handles distribution of a node's confidential identities, and you can see an example of its
use in ``TwoPartyTradeFlow.kt``:
``IdentitySyncFlow`` is divided into two parts:
* ``IdentitySyncFlow.Send``
* ``IdentitySyncFlow.Receive``
``IdentitySyncFlow.Send`` is invoked by the party initiating the identity synchronization:
.. container:: codeset
@ -106,33 +109,40 @@ use in ``TwoPartyTradeFlow.kt``:
The identity synchronization flow goes through the following key steps:
1. Extract participant identities from all input and output states. Filter this set down to confidential identities
of the flow's well known identity. Required signers on commands are currently ignored as they are presumed to be
included in the participants on states, or to be well known identities of services (such as an oracle service).
1. Extract participant identities from all input and output states and remove any well known identities. Required
signers on commands are currently ignored as they are presumed to be included in the participants on states, or to
be well-known identities of services (such as an oracle service)
2. For each counterparty node, send a list of the public keys of the confidential identities, and receive back a list
of those the counterparty needs the certificate path for.
3. Verify the requested list of identities contains only confidential identities in the offered list, and abort otherwise.
4. Send the requested confidential identities as ``PartyAndCertificate`` instances to the counterparty.
of those the counterparty needs the certificate path for
3. Verify the requested list of identities contains only confidential identities in the offered list, and abort
otherwise
4. Send the requested confidential identities as ``PartyAndCertificate`` instances to the counterparty
.. note:: ``IdentitySyncFlow`` works on a push basis. Receiving nodes can only request confidential identities being
offered by the initiating node. There is no standard flow for nodes to collect
confidential identities before assembling a transaction, and this is left for individual flows to manage if required.
.. note:: ``IdentitySyncFlow`` works on a push basis. The initiating node can only send confidential identities it has
the X.509 certificates for, and the remote nodes can only request confidential identities being offered (are
referenced in the transaction passed to the initiating flow). There is no standard flow for nodes to collect
confidential identities before assembling a transaction, and this is left for individual flows to manage if
required.
``IdentitySyncFlow`` will serve only confidential identities in the provided transaction, limited to those that are
signed by the well known identity the flow is initiated by. This is done to avoid a risk of a node including
states it doesn't have the well known identity of participants in, to try convincing one of its counterparties to
reveal the identity. In case of a more complex transaction where multiple well known identities need confidential
identities distributed this flow should be run by each node in turn. For example:
Meanwhile, ``IdentitySyncFlow.Receive`` is invoked by all the other (non-initiating) parties involved in the identity
synchronization process:
.. container:: codeset
.. literalinclude:: ../../finance/src/main/kotlin/net/corda/finance/flows/TwoPartyTradeFlow.kt
:language: kotlin
:start-after: DOCSTART 07
:end-before: DOCEND 07
:dedent: 12
``IdentitySyncFlow`` will serve all confidential identities in the provided transaction, irrespective of well-known
identity. This is important for more complex transaction cases with 3+ parties, for example:
* Alice is building the transaction, and provides some input state *x* owned by a confidential identity of Alice
* Bob provides some input state *y* owned by a confidential identity of Bob
* Charlie provides some input state *z* owned by a confidential identity of Charlie
Alice, Bob and Charlie must all run ``IdentitySyncFlow`` to send their involved confidential identities to the other
parties. For an illustration of the security implications of not requiring this, consider:
1. Alice is building the transaction, and provides some input state *x* owned by a confidential identity of Alice
2. Bob provides some input state *y* owned by a confidential identity it doesn't know the well known identity of, but
Alice does.
3. Alice runs ``IdentitySyncFlow`` and sends not just their confidential identity, but also the confidential identity
in state *y*, violating the privacy model.
Alice may know all of the confidential identities ahead of time, but Bob not know about Charlie's and vice-versa.
The assembled transaction therefore has three input states *x*, *y* and *z*, for which only Alice possesses
certificates for all confidential identities. ``IdentitySyncFlow`` must send not just Alice's confidential identity but
also any other identities in the transaction to the Bob and Charlie.

View File

@ -155,9 +155,9 @@ A CorDapp template that you can use as the basis for your own CorDapps is availa
https://github.com/corda/cordapp-template-kotlin.git
And a simple example CorDapp for you to explore basic concepts is available here:
And a list of simple sample CorDapps for you to explore basic concepts is available here:
https://github.com/corda/cordapp-example.git
https://www.corda.net/samples/
You can clone these repos to your local machine by running the command ``git clone [repo URL]``.
@ -168,9 +168,9 @@ The best way to check that everything is working fine is by taking a deeper look
Next, you should read through :doc:`Corda Key Concepts <key-concepts>` to understand how Corda works.
By then, you'll be ready to start writing your own CorDapps. Learn how to do this in the
:doc:`Hello, World tutorial <hello-world-index>`. You may want to refer to the :doc:`API documentation <corda-api>` along the
way.
You'll then be ready to start writing your own CorDapps. Learn how to do this in the
:doc:`Hello, World tutorial <hello-world-index>`. You'll want to refer to the :doc:`API docs <api-index>`, the
:doc:`flow cookbook <flow-cookbook>` and the `samples <https://www.corda.net/samples/>`_ along the way.
If you encounter any issues, please see the :doc:`troubleshooting` page, or get in touch with us on the
`forums <https://discourse.corda.net/>`_ or via `slack <http://slack.corda.net/>`_.

View File

@ -6,6 +6,6 @@ Quickstart
getting-set-up
tutorial-cordapp
running-the-demos
Sample CorDapps <https://www.corda.net/samples/>
building-against-master
CLI-vs-IDE

View File

@ -1,437 +0,0 @@
Running the demos
=================
.. contents::
The `Corda repository <https://github.com/corda/corda>`_ contains a number of demo programs demonstrating
Corda's functionality:
1. The :ref:`trader-demo`, which shows a delivery-vs-payment atomic swap of commercial paper for cash
2. The :ref:`irs-demo`, which shows two nodes establishing an interest rate swap and performing fixings with a
rates oracle
3. The :ref:`attachment-demo`, which demonstrates uploading attachments to nodes
4. The :ref:`notary-demo`, which shows three different types of notaries and a single node getting multiple transactions
notarised
5. The :ref:`bank-of-corda-demo`, which shows a node acting as an issuer of assets (the Bank of Corda) while remote client
applications request issuance of some cash on behalf of a node called Big Corporation
If any of the demos don't work, please raise an issue on `GitHub <https://github.com/corda/corda/issues>`_.
.. note:: If you are running the demos from the command line in Linux (but not macOS), you may have to install xterm.
.. note:: If you would like to see flow activity on the nodes type in the node terminal ``flow watch``.
.. _trader-demo:
Trader demo
-----------
This demo brings up four nodes: Bank A, Bank B, Bank Of Corda, and a notary/network map node that they all use. Bank A will
be the buyer, and requests some cash from the Bank of Corda in order to acquire commercial paper from Bank B, the seller.
To run from the command line in Unix:
1. Run ``./gradlew samples:trader-demo:deployNodes`` to create a set of configs and installs under ``samples/trader-demo/build/nodes``
2. Run ``./samples/trader-demo/build/nodes/runnodes`` to open up four new terminals with the four nodes
3. Run ``./gradlew samples:trader-demo:runBank`` to instruct the bank node to issue cash and commercial paper to the buyer and seller nodes respectively.
4. Run ``./gradlew samples:trader-demo:runSeller`` to trigger the transaction. If you entered ``flow watch``
you can see flows running on both sides of transaction. Additionally you should see final trade information displayed
to your terminal.
To run from the command line in Windows:
1. Run ``gradlew samples:trader-demo:deployNodes`` to create a set of configs and installs under ``samples\trader-demo\build\nodes``
2. Run ``samples\trader-demo\build\nodes\runnodes`` to open up four new terminals with the four nodes
3. Run ``gradlew samples:trader-demo:runBank`` to instruct the buyer node to request issuance of some cash from the Bank of Corda node
4. Run ``gradlew samples:trader-demo:runSeller`` to trigger the transaction. If you entered ``flow watch``
you can see flows running on both sides of transaction. Additionally you should see final trade information displayed
to your terminal.
.. _irs-demo:
IRS demo
--------
This demo brings up three nodes: Bank A, Bank B and a node that simultaneously runs a notary, a network map and an interest rates
oracle. The two banks agree on an interest rate swap, and then do regular fixings of the deal as the time
on a simulated clock passes.
To run from the command line in Unix:
1. Run ``./gradlew samples:irs-demo:deployNodes`` to install configs and a command line tool under ``samples/irs-demo/build``
2. Run ``./gradlew samples:irs-demo:installDist``
3. Move to the ``samples/irs-demo/build`` directory
4. Run ``./nodes/runnodes`` to open up three new terminals with the three nodes (you may have to install xterm).
To run from the command line in Windows:
1. Run ``gradlew.bat samples:irs-demo:deployNodes`` to install configs and a command line tool under ``samples\irs-demo\build``
2. Run ``gradlew.bat samples:irs-demo:installDist``
3. Run ``cd samples\irs-demo\build`` to change current working directory
4. Run ``nodes\runnodes`` to open up several 6 terminals, 2 for each node. First terminal is a web-server associated with every node and second one is Corda interactive shell for the node.
This demo also has a web app. To use this, run nodes and then navigate to
http://localhost:10007/web/irsdemo and http://localhost:10010/web/irsdemo to see each node's view of the ledger.
To use the web app, click the "Create Deal" button, fill in the form, then click the "Submit" button. You can then
use the time controls at the top left of the home page to run the fixings. Click any individual trade in the blotter to view it.
.. note:: The IRS web UI currently has a bug when changing the clock time where it may show no numbers or apply fixings inconsistently.
The issues will be addressed in a future milestone release. Meanwhile, you can take a look at a simpler oracle example https://github.com/corda/oracle-example
.. _attachment-demo:
Attachment demo
---------------
This demo brings up three nodes, and sends a transaction containing an attachment from one to the other.
To run from the command line in Unix:
1. Run ``./gradlew samples:attachment-demo:deployNodes`` to create a set of configs and installs under ``samples/attachment-demo/build/nodes``
2. Run ``./samples/attachment-demo/build/nodes/runnodes`` to open up three new terminal tabs/windows with the three nodes and webserver for BankB
3. Run ``./gradlew samples:attachment-demo:runRecipient``, which will block waiting for a trade to start
4. Run ``./gradlew samples:attachment-demo:runSender`` in another terminal window to send the attachment. Now look at the other windows to
see the output of the demo
To run from the command line in Windows:
1. Run ``gradlew samples:attachment-demo:deployNodes`` to create a set of configs and installs under ``samples\attachment-demo\build\nodes``
2. Run ``samples\attachment-demo\build\nodes\runnodes`` to open up three new terminal tabs/windows with the three nodes and webserver for BankB
3. Run ``gradlew samples:attachment-demo:runRecipient``, which will block waiting for a trade to start
4. Run ``gradlew samples:attachment-demo:runSender`` in another terminal window to send the attachment. Now look at the other windows to
see the output of the demo
.. _notary-demo:
Notary demo
-----------
This demo shows a party getting transactions notarised by either a single-node or a distributed notary service.
All versions of the demo start two counterparty nodes.
One of the counterparties will generate transactions that transfer a self-issued asset to the other party and submit them for notarisation.
* The `Raft <https://raft.github.io/>`_ version of the demo will start three distributed notary nodes.
* The `BFT SMaRt <https://bft-smart.github.io/library/>`_ version of the demo will start four distributed notary nodes.
* The Single version of the demo will start a single-node validating notary service.
* The Custom version of the demo will load and start a custom single-node notary service that is defined the demo CorDapp.
The output will display a list of notarised transaction IDs and corresponding signer public keys. In the Raft distributed notary,
every node in the cluster can service client requests, and one signature is sufficient to satisfy the notary composite key requirement.
In the BFT SMaRt distributed notary, three signatures are required.
You will notice that successive transactions get signed by different members of the cluster (usually allocated in a random order).
To run the Raft version of the demo from the command line in Unix:
1. Run ``./gradlew samples:notary-demo:deployNodes``, which will create node directories for all versions of the demo,
with configs under ``samples/notary-demo/build/nodes/nodesRaft`` (``nodesBFT``, ``nodesSingle``, and ``nodesCustom`` for
BFT, Single and Custom notaries respectively).
2. Run ``./samples/notary-demo/build/nodes/nodesRaft/runnodes``, which will start the nodes in separate terminal windows/tabs.
Wait until a "Node started up and registered in ..." message appears on each of the terminals
3. Run ``./gradlew samples:notary-demo:notarise`` to make a call to the "Party" node to initiate notarisation requests
In a few seconds you will see a message "Notarised 10 transactions" with a list of transaction ids and the signer public keys
To run from the command line in Windows:
1. Run ``gradlew samples:notary-demo:deployNodes``, which will create all three types of notaries' node directories
with configs under ``samples/notary-demo/build/nodes/nodesRaft`` (``nodesBFT``, ``nodesSingle``, and ``nodesCustom`` for
BFT, Single and Custom notaries respectively).
2. Run ``samples\notary-demo\build\nodes\nodesRaft\runnodes``, which will start the nodes in separate terminal windows/tabs.
Wait until a "Node started up and registered in ..." message appears on each of the terminals
3. Run ``gradlew samples:notary-demo:notarise`` to make a call to the "Party" node to initiate notarisation requests
In a few seconds you will see a message "Notarised 10 transactions" with a list of transaction ids and the signer public keys
To run the BFT SMaRt notary demo, use ``nodesBFT`` instead of ``nodesRaft`` in the path (you will see messages from notary nodes
trying to communicate each other sometime with connection errors, that's normal). For a single notary node, use ``nodesSingle``.
For the custom notary service use ``nodesCustom`.
Distributed notary nodes store consumed states in a replicated commit log, which is backed by a H2 database on each node.
You can ascertain that the commit log is synchronised across the cluster by accessing and comparing each of the nodes' backing stores
by using the H2 web console:
- Firstly, download `H2 web console <http://www.h2database.com/html/download.html>`_ (download the "platform-independent zip"),
and start it using a script in the extracted folder: ``sh h2/bin/h2.sh`` (or ``h2\bin\h2`` for Windows)
- If you are uncertain as to which version of h2 to install or if you have connectivity issues, refer to ``build.gradle``
located in the corda directory and locate ``h2_version``. Use a client of the same major version - even if still in beta.
- The H2 web console should start up in a web browser tab. To connect we first need to obtain a JDBC connection string.
Each node outputs its connection string in the terminal window as it starts up. In a terminal window where a **notary** node is running,
look for the following string:
``Database connection url is : jdbc:h2:tcp://10.18.0.150:56736/node``
You can use the string on the right to connect to the h2 database: just paste it into the `JDBC URL` field and click *Connect*.
You will be presented with a web application that enumerates all the available tables and provides an interface for you to query them using SQL
- The committed states are stored in the ``NOTARY_COMMITTED_STATES`` table (for Raft) or ``NODE_BFT_SMART_NOTARY_COMMITTED_STATES`` (for BFT).
Note that in the Raft case the raw data is not human-readable, but we're only interested in the row count for this demo
.. _bank-of-corda-demo:
Bank Of Corda demo
------------------
This demo brings up three nodes: a notary, a node acting as the Bank of Corda that accepts requests for issuance of some asset
and a node acting as Big Corporation which requests issuance of an asset (cash in this example).
Upon receipt of a request the Bank of Corda node self-issues the asset and then transfers ownership to the requester
after successful notarisation and recording of the issue transaction on the ledger.
.. note:: The Bank of Corda is somewhat like a "Bitcoin faucet" that dispenses free bitcoins to developers for
testing and experimentation purposes.
To run from the command line in Unix:
1. Run ``./gradlew samples:bank-of-corda-demo:deployNodes`` to create a set of configs and installs under ``samples/bank-of-corda-demo/build/nodes``
2. Run ``./samples/bank-of-corda-demo/build/nodes/runnodes`` to open up three new terminal tabs/windows with the three nodes
3. Run ``./gradlew samples:bank-of-corda-demo:runRPCCashIssue`` to trigger a cash issuance request
4. Run ``./gradlew samples:bank-of-corda-demo:runWebCashIssue`` to trigger another cash issuance request.
Now look at your terminal tab/window to see the output of the demo
To run from the command line in Windows:
1. Run ``gradlew samples:bank-of-corda-demo:deployNodes`` to create a set of configs and installs under ``samples\bank-of-corda-demo\build\nodes``
2. Run ``samples\bank-of-corda-demo\build\nodes\runnodes`` to open up three new terminal tabs/windows with the three nodes
3. Run ``gradlew samples:bank-of-corda-demo:runRPCCashIssue`` to trigger a cash issuance request
4. Run ``gradlew samples:bank-of-corda-demo:runWebCashIssue`` to trigger another cash issuance request.
Now look at the your terminal tab/window to see the output of the demo
.. note:: To verify that the Bank of Corda node is alive and running, navigate to the following URL:
http://localhost:10007/api/bank/date
In the window you run the command you should see (in case of Web, RPC is simmilar):
- Requesting Cash via Web ...
- Successfully processed Cash Issue request
If you want to see flow activity enter in node's shell ``flow watch``. It will display all state machines
running currently on the node.
Launch the Explorer application to visualize the issuance and transfer of cash for each node:
``./gradlew tools:explorer:run`` (on Unix) or ``gradlew tools:explorer:run`` (on Windows)
Using the following login details:
- For the Bank of Corda node: localhost / port 10006 / username bankUser / password test
- For the Big Corporation node: localhost / port 10009 / username bigCorpUser / password test
See https://docs.corda.net/node-explorer.html for further details on usage.
.. _simm-demo:
SIMM and Portfolio Demo - aka the Initial Margin Agreement Demo
---------------------------------------------------------------
Background and SIMM Introduction
********************************
This app is a demonstration of how Corda can be used for the real world requirement of initial margin calculation and
agreement; featuring the integration of complex and industry proven third party libraries into Corda nodes.
SIMM is an acronym for "Standard Initial Margin Model". It is effectively the calculation of a "margin" that is paid
by one party to another when they agree a trade on certain types of transaction.
The SIMM was introduced to standardise the calculation of how much margin counterparties charge each other on their
bilateral transactions. Before SIMM, each counterparty computed margins according to its own model and it was made it very
difficult to agree the exact margin with the counterparty that faces the same trade on the other side.
To enact this, in September 2016, the ISDA committee - with full backing from various governing bodies -
`issued a ruling on what is known as the ISDA SIMM ™ model <http://www2.isda.org/news/isda-simm-deployed-today-new-industry-standard-for-calculating-initial-margin-widely-adopted-by-market-participants>`_,
a way of fairly and consistently calculating this margin. Any parties wishing to trade a financial product that is
covered under this ruling would, independently, use this model and calculate their margin payment requirement,
agree it with their trading counterparty and then pay (or receive, depending on the results of this calculation)
this amount. In the case of disagreement that is not resolved in a timely fashion, this payment would increase
and so therefore it is in the parties' interest to reach agreement in as short as time frame as possible.
To be more accurate, the SIMM calculation is not performed on just one trade - it is calculated on an aggregate of
intermediary values (which in this model are sensitivities to risk factors) from a portfolio of trades; therefore
the input to a SIMM is actually this data, not the individual trades themselves.
Also note that implementations of the SIMM are actually protected and subject to license restrictions by ISDA
(this is due to the model itself being protected). We were fortunate enough to technically partner with
`OpenGamma <http://www.opengamma.com>`_ who allowed us to demonstrate the SIMM process using their proprietary model.
In the source code released, we have replaced their analytics engine with very simple stub functions that allow
the process to run without actually calculating correct values, and can easily be swapped out in place for their real libraries.
What happens in the demo (notionally)
*************************************
Preliminaries
- Ensure that there are a number of live trades with another party based on financial products that are covered under the
ISDA SIMM agreement (if none, then use the demo to enter some simple trades as described below).
Initial Margin Agreement Process
- Agree that one will be performing the margining calculation against a portfolio of trades with another party, and agree the trades in that portfolio. In practice, one node will start the flow but it does not matter which node does.
- Individually (at the node level), identify the data (static, reference etc) one will need in order to be able to calculate the metrics on those trades
- Confirm with the other counterparty the dataset from the above set
- Calculate any intermediary steps and values needed for the margin calculation (ie sensitivities to risk factors)
- Agree on the results of these steps
- Calculate the initial margin
- Agree on the calculation of the above with the other party
- In practice, pay (or receive) this margin (omitted for the sake of complexity for this example)
Demo execution (step by step)
*****************************
**Setting up the Corda infrastructure**
To run from the command line in Unix:
1. Deploy the nodes using ``./gradlew samples:simm-valuation-demo:deployNodes``
2. Run the nodes using ``./samples/simm-valuation-demo/build/nodes/runnodes``
To run from the command line in Windows:
1. Deploy the nodes using ``gradlew samples:simm-valuation-demo:deployNodes``
2. Run the nodes using ``samples\simm-valuation-demo\build\nodes\runnodes``
**Getting Bank A's details**
From the command line run
.. sourcecode:: bash
curl http://localhost:10005/api/simmvaluationdemo/whoami
The response should be something like
.. sourcecode:: none
{
"self" : {
"id" : "8Kqd4oWdx4KQGHGQW3FwXHQpjiv7cHaSsaAWMwRrK25bBJj792Z4rag7EtA",
"text" : "C=GB,L=London,O=Bank A"
},
"counterparties" : [
{
"id" : "8Kqd4oWdx4KQGHGL1DzULumUmZyyokeSGJDY1n5M6neUfAj2sjbf65wYwQM",
"text" : "C=JP,L=Tokyo,O=Bank C"
},
{
"id" : "8Kqd4oWdx4KQGHGTBm34eCM2nrpcWKeM1ZG3DUYat3JTFUQTwB3Lv2WbPM8",
"text" : "C=US,L=New York,O=Bank B"
}
]
}
Now, if we ask the same question of Bank C we will see that it's id matches the id for Bank C as a counter
party to Bank A and Bank A will appear as a counter party
.. sourcecode:: bash
curl -i -H "Content-Type: application/json" -X GET http://localhost:10011/api/simmvaluationdemo/whoami
**Creating a trade with Bank C**
In what follows, we assume we are Bank A (which is listening on port 10005)
Notice the id field in the output of the ``whoami`` command. We are going to use the id assocatied
with Bank C, one of our counter parties, to create a trade. The general command for this is:
.. sourcecode:: bash
curl -i -H "Content-Type: application/json" -X PUT -d <<<JSON representation of the trade>>> http://localhost:10005/api/simmvaluationdemo/<<<counter party id>>>/trades
where the representation of the trade is
.. sourcecode:: none
{
"id" : "trade1",
"description" : "desc",
"tradeDate" : [ 2016, 6, 6 ],
"convention" : "EUR_FIXED_1Y_EURIBOR_3M",
"startDate" : [ 2016, 6, 6 ],
"endDate" : [ 2020, 1, 2 ],
"buySell" : "BUY",
"notional" : "1000",
"fixedRate" : "0.1"
}
Continuing our example, the specific command we would run is
.. sourcecode:: bash
curl -i -H "Content-Type: application/json" \
-X PUT \
-d '{"id":"trade1","description" : "desc","tradeDate" : [ 2016, 6, 6 ], "convention" : "EUR_FIXED_1Y_EURIBOR_3M", "startDate" : [ 2016, 6, 6 ], "endDate" : [ 2020, 1, 2 ], "buySell" : "BUY", "notional" : "1000", "fixedRate" : "0.1"}' \
http://localhost:10005/api/simmvaluationdemo/8Kqd4oWdx4KQGHGL1DzULumUmZyyokeSGJDY1n5M6neUfAj2sjbf65wYwQM/trades
With an expected response of
.. sourcecode:: none
HTTP/1.1 202 Accepted
Date: Thu, 28 Sep 2017 17:19:39 GMT
Content-Type: text/plain
Access-Control-Allow-Origin: *
Content-Length: 2
Server: Jetty(9.3.9.v20160517)
**Verifying trade completion**
With the trade completed and stored by both parties, the complete list of trades with our couterparty can be seen with the following command
.. sourcecode:: bash
curl -X GET http://localhost:10005/api/simmvaluationdemo/<<<counter party id>>>/trades
The command for our example, using Bank A, would thus be
.. sourcecode:: bash
curl -X GET http://localhost:10005/api/simmvaluationdemo/8Kqd4oWdx4KQGHGL1DzULumUmZyyokeSGJDY1n5M6neUfAj2sjbf65wYwQM/trades
whilst a specific trade can be seen with
.. sourcecode:: bash
curl -X GET http://localhost:10005/api/simmvaluationdemo/<<<counter party id>>>/trades/<<<trade id>>>
If we look at the trade we created above, we assigned it the id "trade1", the complete command in this case would be
.. sourcecode:: bash
curl -X GET http://localhost:10005/api/simmvaluationdemo/8Kqd4oWdx4KQGHGL1DzULumUmZyyokeSGJDY1n5M6neUfAj2sjbf65wYwQM/trades/trade1
**Generating a valuation**
.. sourcecode:: bash
curl -i -H "Content-Type: application/json" \
-X POST \
-d <<<JSON representation>>>
http://localhost:10005/api/simmvaluationdemo/<<<counter party id>>>/portfolio/valuations/calculate
Again, the specific command to continue our example would be
.. sourcecode:: bash
curl -i -H "Content-Type: application/json" \
-X POST \
-d '{"valuationDate":[2016,6,6]}' \
http://localhost:10005/api/simmvaluationdemo/8Kqd4oWdx4KQGHGL1DzLumUmZyyokeSGJDY1n5M6neUfAj2sjbf65wYwQM/portfolio/valuations/calculate
**Viewing a valuation**
In the same way we can ask for specific instances of trades with a counter party, we can request details of valuations
.. sourcecode:: bash
curl -i -H "Content-Type: application/json" -X GET http://localhost:10005/api/simmvaluationdemo/<<<counter party id>>>/portfolio/valuations
The specific command for out Bank A example is
.. sourcecode:: bash
curl -i -H "Content-Type: application/json" \
-X GET http://localhost:10005/api/simmvaluationdemo/8Kqd4oWdx4KQGHGL1DzULumUmZyyokeSGJDY1n5M6neUfAj2sjbf65YwQM/portfolio/valuations

View File

@ -87,9 +87,11 @@ object TwoPartyTradeFlow {
// Verify and sign the transaction.
progressTracker.currentStep = VERIFYING_AND_SIGNING
// DOCSTART 07
// Sync identities to ensure we know all of the identities involved in the transaction we're about to
// be asked to sign
subFlow(IdentitySyncFlow.Receive(otherSideSession))
// DOCEND 07
// DOCSTART 5
val signTransactionFlow = object : SignTransactionFlow(otherSideSession, VERIFYING_AND_SIGNING.childProgressTracker()) {

View File

@ -1,14 +1,23 @@
# Attachment Demo
# Attachment Demo
This code demonstrates sending a transaction with an attachment from one to node to another, and the receiving node accessing the attachment.
This demo brings up three nodes, and sends a transaction containing an attachment from one to the other.
Please see the either the [online documentation](https://docs.corda.net/running-the-demos.html#attachment-demo) for more info on the attachment demo, or the [included offline version](../../docs/build/html/running-the-demos.html#attachment-demo).
To run from the command line in Unix:
From the root directory of the repository, run the following commands (on mac / unix, replace `gradle` with `./gradlew`)
1. Run ``./gradlew samples:attachment-demo:deployNodes`` to create a set of configs and installs under
``samples/attachment-demo/build/nodes``
2. Run ``./samples/attachment-demo/build/nodes/runnodes`` to open up three new terminal tabs/windows with the three
nodes and webserver for BankB
3. Run ``./gradlew samples:attachment-demo:runRecipient``, which will block waiting for a trade to start
4. Run ``./gradlew samples:attachment-demo:runSender`` in another terminal window to send the attachment. Now look at
the other windows to see the output of the demo
gradle samples:attachment-demo:deployNodes
To run from the command line in Windows:
./samples/attachment-demo/build/nodes/runnodes
gradle samples:attachment-demo:runRecipient # (in one window)
gradle samples:attachment-demo:runSender # (in another window)
1. Run ``gradlew samples:attachment-demo:deployNodes`` to create a set of configs and installs under
``samples\attachment-demo\build\nodes``
2. Run ``samples\attachment-demo\build\nodes\runnodes`` to open up three new terminal tabs/windows with the three nodes
and webserver for BankB
3. Run ``gradlew samples:attachment-demo:runRecipient``, which will block waiting for a trade to start
4. Run ``gradlew samples:attachment-demo:runSender`` in another terminal window to send the attachment. Now look at the
other windows to see the output of the demo

View File

@ -1,58 +1,53 @@
# Bank of Corda demo
Please see docs/build/html/running-the-demos.html
Bank Of Corda demo
------------------
This program simulates the role of an asset issuing authority (eg. central bank for cash) by accepting requests
from third parties to issue some quantity of an asset and transfer that ownership to the requester.
The issuing authority accepts requests via the [IssuerFlow] flow, self-issues the asset and transfers
ownership to the issue requester. Notarisation and signing form part of the flow.
This demo brings up three nodes: a notary, a node acting as the Bank of Corda that accepts requests for issuance of
some asset and a node acting as Big Corporation which requests issuance of an asset (cash in this example).
The requesting party can be a CorDapp (running locally or remotely to the Bank of Corda node), a remote RPC client or
a Web Client.
Upon receipt of a request the Bank of Corda node self-issues the asset and then transfers ownership to the requester
after successful notarisation and recording of the issue transaction on the ledger.
## Prerequisites
.. note:: The Bank of Corda is somewhat like a "Bitcoin faucet" that dispenses free bitcoins to developers for
testing and experimentation purposes.
You will need to have [JDK 8](http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html)
installed and available on your path.
To run from the command line in Unix:
## Getting Started
1. Run ``./gradlew samples:bank-of-corda-demo:deployNodes`` to create a set of configs and installs under
``samples/bank-of-corda-demo/build/nodes``
2. Run ``./samples/bank-of-corda-demo/build/nodes/runnodes`` to open up three new terminal tabs/windows with the three
nodes
3. Run ``./gradlew samples:bank-of-corda-demo:runRPCCashIssue`` to trigger a cash issuance request
4. Run ``./gradlew samples:bank-of-corda-demo:runWebCashIssue`` to trigger another cash issuance request.
Now look at your terminal tab/window to see the output of the demo
1. Launch the Bank of Corda node (and associated Notary) by running:
[BankOfCordaDriver] --role ISSUER
(to validate your Node is running you can try navigating to this sample link: http://localhost:10005/api/bank/date)
To run from the command line in Windows:
Each of the following commands will launch a separate Node called Big Corporation which will become the owner
of some Cash following an issue request:
1. Run ``gradlew samples:bank-of-corda-demo:deployNodes`` to create a set of configs and installs under
``samples\bank-of-corda-demo\build\nodes``
2. Run ``samples\bank-of-corda-demo\build\nodes\runnodes`` to open up three new terminal tabs/windows with the three
nodes
3. Run ``gradlew samples:bank-of-corda-demo:runRPCCashIssue`` to trigger a cash issuance request
4. Run ``gradlew samples:bank-of-corda-demo:runWebCashIssue`` to trigger another cash issuance request.
Now look at the your terminal tab/window to see the output of the demo
2. Run the Bank of Corda Client driver (to simulate a web issue requester) by running:
[BankOfCordaDriver] --role ISSUE_CASH_WEB
This demonstrates a remote application acting on behalf of the Big Corporation and communicating directly with the
Bank of Corda node via HTTP to request issuance of some cash.
To verify that the Bank of Corda node is alive and running, navigate to the following URL:
http://localhost:10007/api/bank/date
3. Run the Bank of Corda Client driver (to simulate an RPC issue requester) by running:
[BankOfCordaDriver] --role ISSUE_CASH_RPC
Similar to 3 above, but using RPC as the remote communications mechanism.
In the window you run the command you should see (in case of Web, RPC is similar):
## Developer notes
- Requesting Cash via Web ...
- Successfully processed Cash Issue request
Testing of the Bank of Corda application is demonstrated at two levels:
1. Unit testing the flow uses the [LedgerDSL] and [MockServices]. Please see [IssuerFlowTest]
The IssuerFlow is one of several reusable flows defined in the finance package.
2. Integration testing via RPC and HTTP uses the [Driver] DSL to launch standalone node instances
If you want to see flow activity enter in node's shell ``flow watch``. It will display all state machines running
currently on the node.
Security
The RPC API requires a client to pass in user credentials:
client.start("bankUser","test")
which are validated on the Bank of Corda node against those configured at node startup:
User("bankUser", "test", permissions = setOf(startFlowPermission<IssuerFlow.IssuanceRequester>()))
startNode(BOC.name, rpcUsers = listOf(user))
Launch the Explorer application to visualize the issuance and transfer of cash for each node:
Notary
We are using a [SimpleNotaryService] in this example, but could easily switch to a [ValidatingNotaryService]
``./gradlew tools:explorer:run`` (on Unix) or ``gradlew tools:explorer:run`` (on Windows)
## Integration with other Demos and Tools
Using the following login details:
The Bank of Corda issuer node concept has been integrated into the Explorer tool (simulation nodes) and Trader Demo.
- For the Bank of Corda node: localhost / port 10006 / username bankUser / password test
- For the Big Corporation node: localhost / port 10009 / username bigCorpUser / password test
## Further Reading
Tutorials and developer docs for Cordapps and Corda are [here](https://docs.corda.net/).
See https://docs.corda.net/node-explorer.html for further details on usage.

View File

@ -1,7 +1,33 @@
# IRS Demo
This code demonstrates an Interest Rate Swap agreement between two banks, confirming the transaction utilising the services
of a notary and then retrieving and applying interest rates from an oracle service.
This demo brings up three nodes: Bank A, Bank B and a node that simultaneously runs a notary, a network map and an
interest rates oracle. The two banks agree on an interest rate swap, and then do regular fixings of the deal as the
time on a simulated clock passes.
To run from the command line in Unix:
Please see the either the [online documentation](https://docs.corda.net/running-the-demos.html#irs-demo) for more info on the attachment demo, or the [included offline version](../../docs/build/html/running-the-demos.html#irs-demo).
1. Run ``./gradlew samples:irs-demo:deployNodes`` to install configs and a command line tool under
``samples/irs-demo/build``
2. Run ``./gradlew samples:irs-demo:installDist``
3. Move to the ``samples/irs-demo/build`` directory
4. Run ``./nodes/runnodes`` to open up three new terminals with the three nodes (you may have to install xterm)
To run from the command line in Windows:
1. Run ``gradlew.bat samples:irs-demo:deployNodes`` to install configs and a command line tool under
``samples\irs-demo\build``
2. Run ``gradlew.bat samples:irs-demo:installDist``
3. Run ``cd samples\irs-demo\build`` to change current working directory
4. Run ``nodes\runnodes`` to open up several 6 terminals, 2 for each node. First terminal is a web-server associated
with every node and second one is Corda interactive shell for the node
This demo also has a web app. To use this, run nodes and then navigate to http://localhost:10007/web/irsdemo and
http://localhost:10010/web/irsdemo to see each node's view of the ledger.
To use the web app, click the "Create Deal" button, fill in the form, then click the "Submit" button. You can then use
the time controls at the top left of the home page to run the fixings. Click any individual trade in the blotter to
view it.
*Note:* The IRS web UI currently has a bug when changing the clock time where it may show no numbers or apply fixings
inconsistently. The issues will be addressed in a future milestone release. Meanwhile, you can take a look at a simpler
oracle example here: https://github.com/corda/oracle-example.

View File

@ -1,5 +1,61 @@
# Distributed Notary Demo
Notary demo
-----------
This program is a simple demonstration of a node getting multiple transactions notarised by a distributed (Raft or BFT SMaRt) notary.
This demo shows a party getting transactions notarised by either a single-node or a distributed notary service.
All versions of the demo start two counterparty nodes.
Please see docs/build/html/running-the-demos.html to learn how to use this demo.
One of the counterparties will generate transactions that transfer a self-issued asset to the other party and submit
them for notarisation.
The Raft (https://raft.github.io/) version of the demo will start three distributed notary nodes.
The BFT SMaRt (https://bft-smart.github.io/library/) version of the demo will start four distributed notary nodes.
The output will display a list of notarised transaction IDs and corresponding signer public keys. In the Raft distributed notary,
every node in the cluster can service client requests, and one signature is sufficient to satisfy the notary composite key requirement.
In the BFT SMaRt distributed notary, three signatures are required.
You will notice that successive transactions get signed by different members of the cluster (usually allocated in a random order).
To run the Raft version of the demo from the command line in Unix:
1. Run ``./gradlew samples:notary-demo:deployNodes``, which will create all three types of notaries' node directories
with configs under ``samples/notary-demo/build/nodes/nodesRaft`` (``nodesBFT`` and ``nodesSingle`` for BFT and
Single notaries).
2. Run ``./samples/notary-demo/build/nodes/nodesRaft/runnodes``, which will start the nodes in separate terminal windows/tabs.
Wait until a "Node started up and registered in ..." message appears on each of the terminals
3. Run ``./gradlew samples:notary-demo:notarise`` to make a call to the "Party" node to initiate notarisation requests
In a few seconds you will see a message "Notarised 10 transactions" with a list of transaction ids and the signer public keys
To run from the command line in Windows:
1. Run ``gradlew samples:notary-demo:deployNodes``, which will create all three types of notaries' node directories
with configs under ``samples/notary-demo/build/nodes/nodesRaft`` (``nodesBFT`` and ``nodesSingle`` for BFT and
Single notaries).
2. Run ``samples\notary-demo\build\nodes\nodesRaft\runnodes``, which will start the nodes in separate terminal windows/tabs.
Wait until a "Node started up and registered in ..." message appears on each of the terminals
3. Run ``gradlew samples:notary-demo:notarise`` to make a call to the "Party" node to initiate notarisation requests
In a few seconds you will see a message "Notarised 10 transactions" with a list of transaction ids and the signer public keys
To run the BFT SMaRt notary demo, use ``nodesBFT`` instead of ``nodesRaft`` in the path (you will see messages from notary nodes
trying to communicate each other sometime with connection errors, that's normal). For a single notary node, use ``nodesSingle``.
Distributed notary nodes store consumed states in a replicated commit log, which is backed by a H2 database on each node.
You can ascertain that the commit log is synchronised across the cluster by accessing and comparing each of the nodes' backing stores
by using the H2 web console:
- Firstly, download H2 web console (http://www.h2database.com/html/download.html) (download the "platform-independent zip"),
and start it using a script in the extracted folder: ``sh h2/bin/h2.sh`` (or ``h2\bin\h2`` for Windows)
- If you are uncertain as to which version of h2 to install or if you have connectivity issues, refer to ``build.gradle``
located in the corda directory and locate ``h2_version``. Use a client of the same major version - even if still in beta.
- The H2 web console should start up in a web browser tab. To connect we first need to obtain a JDBC connection string.
Each node outputs its connection string in the terminal window as it starts up. In a terminal window where a **notary** node is running,
look for the following string:
``Database connection url is : jdbc:h2:tcp://10.18.0.150:56736/node``
You can use the string on the right to connect to the h2 database: just paste it into the `JDBC URL` field and click *Connect*.
You will be presented with a web application that enumerates all the available tables and provides an interface for you to query them using SQL
- The committed states are stored in the ``NOTARY_COMMITTED_STATES`` table (for Raft) or ``NODE_BFT_SMART_NOTARY_COMMITTED_STATES`` (for BFT).
Note that in the Raft case the raw data is not human-readable, but we're only interested in the row count for this demo

View File

@ -1,5 +1,28 @@
# Trader Demo
Trader demo
-----------
This code demonstrates four nodes, a notary, an issuer of cash (Bank of Corda), and two parties trading with each other, exchanging cash for a commercial paper.
This demo brings up four nodes: Bank A, Bank B, Bank Of Corda, and a notary/network map node that they all use. Bank A
will be the buyer, and requests some cash from the Bank of Corda in order to acquire commercial paper from Bank B, the
seller.
Please see the either the [online documentation](https://docs.corda.net/running-the-demos.html#trader-demo) for more info on the attachment demo, or the [included offline version](../../docs/build/html/running-the-demos.html#trader-demo).
To run from the command line in Unix:
1. Run ``./gradlew samples:trader-demo:deployNodes`` to create a set of configs and installs under
``samples/trader-demo/build/nodes``
2. Run ``./samples/trader-demo/build/nodes/runnodes`` to open up four new terminals with the four nodes
3. Run ``./gradlew samples:trader-demo:runBank`` to instruct the bank node to issue cash and commercial paper to the
buyer and seller nodes respectively
4. Run ``./gradlew samples:trader-demo:runSeller`` to trigger the transaction. If you entered ``flow watch``, you can
see flows running on both sides of transaction. Additionally you should see final trade information displayed to
your terminal
To run from the command line in Windows:
1. Run ``gradlew samples:trader-demo:deployNodes`` to create a set of configs and installs under
``samples\trader-demo\build\nodes``
2. Run ``samples\trader-demo\build\nodes\runnodes`` to open up four new terminals with the four nodes
3. Run ``gradlew samples:trader-demo:runBank`` to instruct the buyer node to request issuance of some cash from the
Bank of Corda node
4. Run ``gradlew samples:trader-demo:runSeller`` to trigger the transaction. If you entered ``flow watch``, you can see
flows running on both sides of transaction. Additionally you should see final trade information displayed to your
terminal