mirror of
https://github.com/corda/corda.git
synced 2025-06-15 13:48:14 +00:00
Merge remote-tracking branch 'corda/master' into christians_os_merge_20171031
This commit is contained in:
@ -8,8 +8,8 @@
|
||||
<br>
|
||||
API reference: <a href="api/kotlin/corda/index.html">Kotlin</a>/ <a href="api/javadoc/index.html">JavaDoc</a>
|
||||
<br>
|
||||
<a href="https://discourse.corda.net">Discourse Forums</a>
|
||||
<br>
|
||||
<a href="http://slack.corda.net">Slack</a>
|
||||
<br>
|
||||
{% endblock %}
|
||||
<a href="https://stackoverflow.com/questions/tagged/corda">Stack Overflow</a>
|
||||
<br>
|
||||
{% endblock %}
|
@ -6,10 +6,10 @@
|
||||
<br>
|
||||
API reference: <a href="api/kotlin/corda/index.html">Kotlin</a>/ <a href="api/javadoc/index.html">JavaDoc</a>
|
||||
<br>
|
||||
<a href="https://discourse.corda.net">Discourse Forums</a>
|
||||
<br>
|
||||
<a href="http://slack.corda.net">Slack</a>
|
||||
<br>
|
||||
<a href="https://stackoverflow.com/questions/tagged/corda">Stack Overflow</a>
|
||||
<br>
|
||||
<select id="versionDropdown" class="version-dropdown" onChange="window.location.href=this.value"></select>
|
||||
<br>
|
||||
<span style="display:none" id="version">{{ version }}</span>
|
||||
|
@ -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.
|
@ -39,17 +39,17 @@ UNRELEASED
|
||||
``notaryNodeAddress``, ``notaryClusterAddresses`` and ``bftSMaRt`` have also been removed and replaced by a single
|
||||
``notary`` config object. See :doc:`corda-configuration-file` for more details.
|
||||
|
||||
* Gradle task ``deployNodes`` can have an additional parameter `configFile` with the path to a properties file
|
||||
* Gradle task ``deployNodes`` can have an additional parameter ``configFile`` with the path to a properties file
|
||||
to be appended to node.conf.
|
||||
|
||||
* Cordformation node building DSL can have an additional parameter `configFile` with the path to a properties file
|
||||
* Cordformation node building DSL can have an additional parameter ``configFile`` with the path to a properties file
|
||||
to be appended to node.conf.
|
||||
|
||||
* ``FlowLogic`` now has a static method called ``sleep`` which can be used in certain circumstances to help with resolving
|
||||
contention over states in flows. This should be used in place of any other sleep primitive since these are not compatible
|
||||
with flows and their use will be prevented at some point in the future. Pay attention to the warnings and limitations
|
||||
described in the documentation for this method. This helps resolve a bug in ``Cash`` coin selection.
|
||||
A new static property `currentTopLevel` returns the top most `FlowLogic` instance, or null if not in a flow.
|
||||
A new static property ``currentTopLevel`` returns the top most ``FlowLogic`` instance, or null if not in a flow.
|
||||
|
||||
* ``CordaService`` annotated classes should be upgraded to take a constructor parameter of type ``AppServiceHub`` which
|
||||
allows services to start flows marked with the ``StartableByService`` annotation. For backwards compatability
|
||||
@ -67,7 +67,10 @@ UNRELEASED
|
||||
* A new function ``checkCommandVisibility(publicKey: PublicKey)`` has been added to ``FilteredTransaction`` to check
|
||||
if every command that a signer should receive (e.g. an Oracle) is indeed visible.
|
||||
|
||||
* Change the AMQP serialiser to use the oficially assigned R3 identifier rather than a placeholder.
|
||||
* Changed the AMQP serialiser to use the oficially assigned R3 identifier rather than a placeholder.
|
||||
|
||||
* The ``ReceiveTransactionFlow`` can now be told to record the transaction at the same time as receiving it. Using this
|
||||
feature, better support for observer/regulator nodes has been added. See :doc:`tutorial-observer-nodes`.
|
||||
|
||||
.. _changelog_v1:
|
||||
|
||||
@ -372,7 +375,7 @@ Milestone 14
|
||||
use to exclude core Corda JARs from being built into Cordapp fat JARs.
|
||||
|
||||
* ``database`` field in ``AbstractNode`` class has changed the type from ``org.jetbrains.exposed.sql.Database`` to
|
||||
‘net.corda.node.utilities.CordaPersistence’ - no change is needed for the typical use
|
||||
???net.corda.node.utilities.CordaPersistence??? - no change is needed for the typical use
|
||||
(i.e. services.database.transaction { code block } ) however a change is required when Database was explicitly declared
|
||||
|
||||
* ``DigitalSignature.LegallyIdentifiable``, previously used to identify a signer (e.g. in Oracles), has been removed.
|
||||
|
@ -118,13 +118,6 @@ path to the node's base directory.
|
||||
|
||||
Only one of ``raft``, ``bftSMaRt`` or ``custom`` configuration values may be specified.
|
||||
|
||||
:networkMapService: If `null`, or missing the node is declaring itself as the NetworkMapService host. Otherwise this is
|
||||
a config object with the details of the network map service:
|
||||
|
||||
:address: Host and port string of the ArtemisMQ broker hosting the network map node
|
||||
:legalName: Legal name of the node. This is required as part of the TLS host verification process. The node will
|
||||
reject the connection to the network map service if it provides a TLS common name which doesn't match with this value.
|
||||
|
||||
:minimumPlatformVersion: Used by the node if it's running the network map service to enforce a minimum version requirement
|
||||
on registrations - any node on a Platform Version lower than this value will have their registration rejected.
|
||||
Defaults to 1 if absent.
|
||||
|
@ -35,7 +35,7 @@ class CustomVaultQueryTest {
|
||||
"net.corda.docs"
|
||||
)
|
||||
)
|
||||
mockNet.createNotaryNode(legalName = DUMMY_NOTARY.name)
|
||||
mockNet.createNotaryNode()
|
||||
nodeA = mockNet.createPartyNode()
|
||||
nodeB = mockNet.createPartyNode()
|
||||
nodeA.internals.registerInitiatedFlow(TopupIssuerFlow.TopupIssuer::class.java)
|
||||
|
@ -1,8 +1,7 @@
|
||||
package net.corda.docs
|
||||
|
||||
import net.corda.node.services.config.ConfigHelper
|
||||
import net.corda.node.services.config.FullNodeConfiguration
|
||||
import net.corda.nodeapi.config.parseAs
|
||||
import net.corda.node.services.config.parseAsNodeConfiguration
|
||||
import net.corda.verifier.Verifier
|
||||
import org.junit.Test
|
||||
import java.nio.file.Path
|
||||
@ -34,7 +33,7 @@ class ExampleConfigTest {
|
||||
ConfigHelper.loadConfig(
|
||||
baseDirectory = baseDirectory,
|
||||
configFile = it
|
||||
).parseAs<FullNodeConfiguration>()
|
||||
).parseAsNodeConfiguration()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -26,7 +26,7 @@ class FxTransactionBuildTutorialTest {
|
||||
@Before
|
||||
fun setup() {
|
||||
mockNet = MockNetwork(threadPerNode = true, cordappPackages = listOf("net.corda.finance.contracts.asset", CashSchemaV1::class.packageName))
|
||||
mockNet.createNotaryNode(legalName = DUMMY_NOTARY.name)
|
||||
mockNet.createNotaryNode()
|
||||
nodeA = mockNet.createPartyNode()
|
||||
nodeB = mockNet.createPartyNode()
|
||||
nodeB.internals.registerInitiatedFlow(ForeignExchangeRemoteFlow::class.java)
|
||||
|
@ -34,7 +34,7 @@ class WorkflowTransactionBuildTutorialTest {
|
||||
fun setup() {
|
||||
mockNet = MockNetwork(threadPerNode = true, cordappPackages = listOf("net.corda.docs"))
|
||||
// While we don't use the notary, we need there to be one on the network
|
||||
mockNet.createNotaryNode(legalName = DUMMY_NOTARY.name)
|
||||
mockNet.createNotaryNode()
|
||||
val aliceNode = mockNet.createPartyNode(ALICE_NAME)
|
||||
val bobNode = mockNet.createPartyNode(BOB_NAME)
|
||||
aliceNode.internals.registerInitiatedFlow(RecordCompletionFlow::class.java)
|
||||
|
@ -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/>`_.
|
||||
|
@ -10,11 +10,15 @@ quick introduction to distributed ledgers and how Corda is different, then watch
|
||||
<iframe src="https://player.vimeo.com/video/205410473" width="640" height="360" frameborder="0" webkitallowfullscreen mozallowfullscreen allowfullscreen></iframe>
|
||||
</embed>
|
||||
|
||||
Want to see Corda running? Download our demonstration application `DemoBench <https://www.corda.net/downloads/>`_ or follow our :doc:`quickstart guide </quickstart-index>`.
|
||||
Want to see Corda running? Download our demonstration application `DemoBench <https://www.corda.net/downloads/>`_ or
|
||||
follow our :doc:`quickstart guide </quickstart-index>`.
|
||||
|
||||
If you want to start coding on Corda, then familiarise yourself with the :doc:`key concepts </key-concepts>`, then read our :doc:`Hello, World! tutorial </hello-world-index>`. For the background behind Corda, read the non-technical `introductory white paper`_ or for more detail, the `technical white paper`_.
|
||||
If you want to start coding on Corda, then familiarise yourself with the :doc:`key concepts </key-concepts>`, then read
|
||||
our :doc:`Hello, World! tutorial </hello-world-index>`. For the background behind Corda, read the non-technical
|
||||
`introductory white paper`_ or for more detail, the `technical white paper`_.
|
||||
|
||||
If you have questions or comments, then get in touch with us either on `Slack <https://slack.corda.net/>`_, `Discourse <https://discourse.corda.net/>`_, or write a question on `stackoverflow <https://stackoverflow.com/questions/tagged/corda>`_ .
|
||||
If you have questions or comments, then get in touch on `Slack <https://slack.corda.net/>`_ or write a question on
|
||||
`Stack Overflow <https://stackoverflow.com/questions/tagged/corda>`_ .
|
||||
|
||||
We look forward to seeing what you can do with Corda!
|
||||
|
||||
|
@ -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
|
@ -6,6 +6,9 @@ Here are release notes for each snapshot release from M9 onwards.
|
||||
Unreleased
|
||||
----------
|
||||
|
||||
Support for observer/regulator nodes has returned. Read :doc:`tutorial-observer-nodes` to learn more or examine the
|
||||
interest rate swaps demo.
|
||||
|
||||
Release 1.0
|
||||
-----------
|
||||
Corda 1.0 is finally here!
|
||||
|
@ -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
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
42
docs/source/tutorial-observer-nodes.rst
Normal file
42
docs/source/tutorial-observer-nodes.rst
Normal file
@ -0,0 +1,42 @@
|
||||
.. highlight:: kotlin
|
||||
.. raw:: html
|
||||
|
||||
<script type="text/javascript" src="_static/jquery.js"></script>
|
||||
<script type="text/javascript" src="_static/codesets.js"></script>
|
||||
|
||||
Observer nodes
|
||||
==============
|
||||
|
||||
Posting transactions to an observer node is a common requirement in finance, where regulators often want
|
||||
to receive comprehensive reporting on all actions taken. By running their own node, regulators can receive a stream
|
||||
of digitally signed, de-duplicated reports useful for later processing.
|
||||
|
||||
Adding support for observer nodes to your application is easy. The IRS (interest rate swap) demo shows to do it.
|
||||
|
||||
Just define a new flow that wraps the SendTransactionFlow/ReceiveTransactionFlow, as follows:
|
||||
|
||||
.. container:: codeset
|
||||
|
||||
.. literalinclude:: ../../samples/irs-demo/cordapp/src/main/kotlin/net/corda/irs/flows/AutoOfferFlow.kt
|
||||
:language: kotlin
|
||||
:start-after: DOCSTART 1
|
||||
:end-before: DOCEND 1
|
||||
|
||||
In this example, the ``AutoOfferFlow`` is the business logic, and we define two very short and simple flows to send
|
||||
the transaction to the regulator. There are two important aspects to note here:
|
||||
|
||||
1. The ``ReportToRegulatorFlow`` is marked as an ``@InitiatingFlow`` because it will start a new conversation, context
|
||||
free, with the regulator.
|
||||
2. The ``ReceiveRegulatoryReportFlow`` uses ``ReceiveTransactionFlow`` in a special way - it tells it to send the
|
||||
transaction to the vault for processing, including all states even if not involving our public keys. This is required
|
||||
because otherwise the vault will ignore states that don't list any of the node's public keys, but in this case,
|
||||
we do want to passively observe states we can't change. So overriding this behaviour is required.
|
||||
|
||||
If the states define a relational mapping (see :doc:`api-persistence`) then the regulator will be able to query the
|
||||
reports from their database and observe new transactions coming in via RPC.
|
||||
|
||||
.. warning:: Nodes which act as both observers and which directly take part in the ledger are not supported at this
|
||||
time. In particular, coin selection may return states which you do not have the private keys to be able to sign
|
||||
for. Future versions of Corda may address this issue, but for now, if you wish to both participate in the ledger
|
||||
and also observe transactions that you can't sign for you will need to run two nodes and have two separate
|
||||
identities.
|
@ -19,4 +19,5 @@ Tutorials
|
||||
tutorial-custom-notary
|
||||
tutorial-tear-offs
|
||||
tutorial-attachments
|
||||
event-scheduling
|
||||
event-scheduling
|
||||
tutorial-observer-nodes
|
Reference in New Issue
Block a user