diff --git a/docs/build/doctrees/CLI-vs-IDE.doctree b/docs/build/doctrees/CLI-vs-IDE.doctree
index 5b06afa9fe..6a63c1332b 100644
Binary files a/docs/build/doctrees/CLI-vs-IDE.doctree and b/docs/build/doctrees/CLI-vs-IDE.doctree differ
diff --git a/docs/build/doctrees/azure-vm.doctree b/docs/build/doctrees/azure-vm.doctree
new file mode 100644
index 0000000000..0306711118
Binary files /dev/null and b/docs/build/doctrees/azure-vm.doctree differ
diff --git a/docs/build/doctrees/building-the-docs.doctree b/docs/build/doctrees/building-the-docs.doctree
index 2a8c445d6e..fdf5cc568d 100644
Binary files a/docs/build/doctrees/building-the-docs.doctree and b/docs/build/doctrees/building-the-docs.doctree differ
diff --git a/docs/build/doctrees/clauses.doctree b/docs/build/doctrees/clauses.doctree
index b2cd0fba92..7695d55a80 100644
Binary files a/docs/build/doctrees/clauses.doctree and b/docs/build/doctrees/clauses.doctree differ
diff --git a/docs/build/doctrees/clientrpc.doctree b/docs/build/doctrees/clientrpc.doctree
index c1a20601d3..ad6bf813f7 100644
Binary files a/docs/build/doctrees/clientrpc.doctree and b/docs/build/doctrees/clientrpc.doctree differ
diff --git a/docs/build/doctrees/codestyle.doctree b/docs/build/doctrees/codestyle.doctree
index 39c34920e6..ec95623ec2 100644
Binary files a/docs/build/doctrees/codestyle.doctree and b/docs/build/doctrees/codestyle.doctree differ
diff --git a/docs/build/doctrees/consensus.doctree b/docs/build/doctrees/consensus.doctree
index c29327ebe2..f25588c6b9 100644
Binary files a/docs/build/doctrees/consensus.doctree and b/docs/build/doctrees/consensus.doctree differ
diff --git a/docs/build/doctrees/contract-catalogue.doctree b/docs/build/doctrees/contract-catalogue.doctree
index 5b6c9c1426..05a82affad 100644
Binary files a/docs/build/doctrees/contract-catalogue.doctree and b/docs/build/doctrees/contract-catalogue.doctree differ
diff --git a/docs/build/doctrees/contract-irs.doctree b/docs/build/doctrees/contract-irs.doctree
index bd1c9136a5..cfa59c2d43 100644
Binary files a/docs/build/doctrees/contract-irs.doctree and b/docs/build/doctrees/contract-irs.doctree differ
diff --git a/docs/build/doctrees/corda-configuration-file.doctree b/docs/build/doctrees/corda-configuration-file.doctree
index 555547b945..7e42fd4d90 100644
Binary files a/docs/build/doctrees/corda-configuration-file.doctree and b/docs/build/doctrees/corda-configuration-file.doctree differ
diff --git a/docs/build/doctrees/corda-plugins.doctree b/docs/build/doctrees/corda-plugins.doctree
index 567577f104..58d006db42 100644
Binary files a/docs/build/doctrees/corda-plugins.doctree and b/docs/build/doctrees/corda-plugins.doctree differ
diff --git a/docs/build/doctrees/creating-a-cordapp.doctree b/docs/build/doctrees/creating-a-cordapp.doctree
index b78077a7ae..3c9ecf1c6d 100644
Binary files a/docs/build/doctrees/creating-a-cordapp.doctree and b/docs/build/doctrees/creating-a-cordapp.doctree differ
diff --git a/docs/build/doctrees/data-model.doctree b/docs/build/doctrees/data-model.doctree
index 8feeb14d5c..453796f1df 100644
Binary files a/docs/build/doctrees/data-model.doctree and b/docs/build/doctrees/data-model.doctree differ
diff --git a/docs/build/doctrees/environment.pickle b/docs/build/doctrees/environment.pickle
index a6d6f7caed..3dfe9a9d66 100644
Binary files a/docs/build/doctrees/environment.pickle and b/docs/build/doctrees/environment.pickle differ
diff --git a/docs/build/doctrees/event-scheduling.doctree b/docs/build/doctrees/event-scheduling.doctree
index f4653ee3b9..b994a49aa9 100644
Binary files a/docs/build/doctrees/event-scheduling.doctree and b/docs/build/doctrees/event-scheduling.doctree differ
diff --git a/docs/build/doctrees/flow-state-machines.doctree b/docs/build/doctrees/flow-state-machines.doctree
index 88f175a717..314b942153 100644
Binary files a/docs/build/doctrees/flow-state-machines.doctree and b/docs/build/doctrees/flow-state-machines.doctree differ
diff --git a/docs/build/doctrees/flow-testing.doctree b/docs/build/doctrees/flow-testing.doctree
index b6174aab62..79cddcd92e 100644
Binary files a/docs/build/doctrees/flow-testing.doctree and b/docs/build/doctrees/flow-testing.doctree differ
diff --git a/docs/build/doctrees/further-notes-on-kotlin.doctree b/docs/build/doctrees/further-notes-on-kotlin.doctree
index c821773917..f876eb9c5f 100644
Binary files a/docs/build/doctrees/further-notes-on-kotlin.doctree and b/docs/build/doctrees/further-notes-on-kotlin.doctree differ
diff --git a/docs/build/doctrees/getting-set-up-fault-finding.doctree b/docs/build/doctrees/getting-set-up-fault-finding.doctree
index ab67e0c83d..db9efac42d 100644
Binary files a/docs/build/doctrees/getting-set-up-fault-finding.doctree and b/docs/build/doctrees/getting-set-up-fault-finding.doctree differ
diff --git a/docs/build/doctrees/getting-set-up.doctree b/docs/build/doctrees/getting-set-up.doctree
index d102f89a7e..fe9947e737 100644
Binary files a/docs/build/doctrees/getting-set-up.doctree and b/docs/build/doctrees/getting-set-up.doctree differ
diff --git a/docs/build/doctrees/glossary.doctree b/docs/build/doctrees/glossary.doctree
index 8cb4d95f10..0d2c2db8bb 100644
Binary files a/docs/build/doctrees/glossary.doctree and b/docs/build/doctrees/glossary.doctree differ
diff --git a/docs/build/doctrees/index.doctree b/docs/build/doctrees/index.doctree
index 16cbbf5f55..17208d3c6b 100644
Binary files a/docs/build/doctrees/index.doctree and b/docs/build/doctrees/index.doctree differ
diff --git a/docs/build/doctrees/initial-margin-agreement.doctree b/docs/build/doctrees/initial-margin-agreement.doctree
index 494d10ffe0..865d6f1723 100644
Binary files a/docs/build/doctrees/initial-margin-agreement.doctree and b/docs/build/doctrees/initial-margin-agreement.doctree differ
diff --git a/docs/build/doctrees/inthebox.doctree b/docs/build/doctrees/inthebox.doctree
index dfe534d08c..d0ff2c66bb 100644
Binary files a/docs/build/doctrees/inthebox.doctree and b/docs/build/doctrees/inthebox.doctree differ
diff --git a/docs/build/doctrees/loadtesting.doctree b/docs/build/doctrees/loadtesting.doctree
index 9beba04587..accc4bd99a 100644
Binary files a/docs/build/doctrees/loadtesting.doctree and b/docs/build/doctrees/loadtesting.doctree differ
diff --git a/docs/build/doctrees/merkle-trees.doctree b/docs/build/doctrees/merkle-trees.doctree
index 9cbaf38d45..8c7e96f6f2 100644
Binary files a/docs/build/doctrees/merkle-trees.doctree and b/docs/build/doctrees/merkle-trees.doctree differ
diff --git a/docs/build/doctrees/messaging.doctree b/docs/build/doctrees/messaging.doctree
index 9db11bad86..e02dbcdcd2 100644
Binary files a/docs/build/doctrees/messaging.doctree and b/docs/build/doctrees/messaging.doctree differ
diff --git a/docs/build/doctrees/network-simulator.doctree b/docs/build/doctrees/network-simulator.doctree
index 7810a3aea2..1bef98d495 100644
Binary files a/docs/build/doctrees/network-simulator.doctree and b/docs/build/doctrees/network-simulator.doctree differ
diff --git a/docs/build/doctrees/node-administration.doctree b/docs/build/doctrees/node-administration.doctree
index df9f9bfae9..b35cc51997 100644
Binary files a/docs/build/doctrees/node-administration.doctree and b/docs/build/doctrees/node-administration.doctree differ
diff --git a/docs/build/doctrees/node-explorer.doctree b/docs/build/doctrees/node-explorer.doctree
index 1ef14ccec9..c78b1a4e49 100644
Binary files a/docs/build/doctrees/node-explorer.doctree and b/docs/build/doctrees/node-explorer.doctree differ
diff --git a/docs/build/doctrees/node-services.doctree b/docs/build/doctrees/node-services.doctree
index 61ddc7df71..a1a7412084 100644
Binary files a/docs/build/doctrees/node-services.doctree and b/docs/build/doctrees/node-services.doctree differ
diff --git a/docs/build/doctrees/oracles.doctree b/docs/build/doctrees/oracles.doctree
index 50043c50af..49b8672028 100644
Binary files a/docs/build/doctrees/oracles.doctree and b/docs/build/doctrees/oracles.doctree differ
diff --git a/docs/build/doctrees/permissioning.doctree b/docs/build/doctrees/permissioning.doctree
index c58effb939..73551da81c 100644
Binary files a/docs/build/doctrees/permissioning.doctree and b/docs/build/doctrees/permissioning.doctree differ
diff --git a/docs/build/doctrees/persistence.doctree b/docs/build/doctrees/persistence.doctree
index 5bb61766d8..d90b368ec2 100644
Binary files a/docs/build/doctrees/persistence.doctree and b/docs/build/doctrees/persistence.doctree differ
diff --git a/docs/build/doctrees/publishing-corda.doctree b/docs/build/doctrees/publishing-corda.doctree
new file mode 100644
index 0000000000..50b8c58014
Binary files /dev/null and b/docs/build/doctrees/publishing-corda.doctree differ
diff --git a/docs/build/doctrees/release-notes.doctree b/docs/build/doctrees/release-notes.doctree
index 2860e474e0..db4b91b30a 100644
Binary files a/docs/build/doctrees/release-notes.doctree and b/docs/build/doctrees/release-notes.doctree differ
diff --git a/docs/build/doctrees/release-process.doctree b/docs/build/doctrees/release-process.doctree
index 645b785566..4ae17b6cd7 100644
Binary files a/docs/build/doctrees/release-process.doctree and b/docs/build/doctrees/release-process.doctree differ
diff --git a/docs/build/doctrees/running-a-notary.doctree b/docs/build/doctrees/running-a-notary.doctree
index e416216333..dcc6dc3a1d 100644
Binary files a/docs/build/doctrees/running-a-notary.doctree and b/docs/build/doctrees/running-a-notary.doctree differ
diff --git a/docs/build/doctrees/running-the-demos.doctree b/docs/build/doctrees/running-the-demos.doctree
index 994fe60eff..09e811d6c8 100644
Binary files a/docs/build/doctrees/running-the-demos.doctree and b/docs/build/doctrees/running-the-demos.doctree differ
diff --git a/docs/build/doctrees/secure-coding-guidelines.doctree b/docs/build/doctrees/secure-coding-guidelines.doctree
index 87506f879d..6d201b49ce 100644
Binary files a/docs/build/doctrees/secure-coding-guidelines.doctree and b/docs/build/doctrees/secure-coding-guidelines.doctree differ
diff --git a/docs/build/doctrees/setting-up-a-corda-network.doctree b/docs/build/doctrees/setting-up-a-corda-network.doctree
index 3ef82feb25..5558e30700 100644
Binary files a/docs/build/doctrees/setting-up-a-corda-network.doctree and b/docs/build/doctrees/setting-up-a-corda-network.doctree differ
diff --git a/docs/build/doctrees/transaction-data-types.doctree b/docs/build/doctrees/transaction-data-types.doctree
index 5d3f4b842b..e22b5d3053 100644
Binary files a/docs/build/doctrees/transaction-data-types.doctree and b/docs/build/doctrees/transaction-data-types.doctree differ
diff --git a/docs/build/doctrees/tutorial-attachments.doctree b/docs/build/doctrees/tutorial-attachments.doctree
index 9b3599eaf6..37ba955583 100644
Binary files a/docs/build/doctrees/tutorial-attachments.doctree and b/docs/build/doctrees/tutorial-attachments.doctree differ
diff --git a/docs/build/doctrees/tutorial-building-transactions.doctree b/docs/build/doctrees/tutorial-building-transactions.doctree
index 3d2f94419b..e3dc4d1960 100644
Binary files a/docs/build/doctrees/tutorial-building-transactions.doctree and b/docs/build/doctrees/tutorial-building-transactions.doctree differ
diff --git a/docs/build/doctrees/tutorial-clientrpc-api.doctree b/docs/build/doctrees/tutorial-clientrpc-api.doctree
index 829e8aba01..beefc53f07 100644
Binary files a/docs/build/doctrees/tutorial-clientrpc-api.doctree and b/docs/build/doctrees/tutorial-clientrpc-api.doctree differ
diff --git a/docs/build/doctrees/tutorial-contract-clauses.doctree b/docs/build/doctrees/tutorial-contract-clauses.doctree
index 497e021f5a..1155fef12e 100644
Binary files a/docs/build/doctrees/tutorial-contract-clauses.doctree and b/docs/build/doctrees/tutorial-contract-clauses.doctree differ
diff --git a/docs/build/doctrees/tutorial-contract.doctree b/docs/build/doctrees/tutorial-contract.doctree
index 62cb14cfac..854891d8f2 100644
Binary files a/docs/build/doctrees/tutorial-contract.doctree and b/docs/build/doctrees/tutorial-contract.doctree differ
diff --git a/docs/build/doctrees/tutorial-cordapp.doctree b/docs/build/doctrees/tutorial-cordapp.doctree
index 0912907e18..70c76411f0 100644
Binary files a/docs/build/doctrees/tutorial-cordapp.doctree and b/docs/build/doctrees/tutorial-cordapp.doctree differ
diff --git a/docs/build/doctrees/tutorial-integration-testing.doctree b/docs/build/doctrees/tutorial-integration-testing.doctree
index f8930d7caf..1b26def399 100644
Binary files a/docs/build/doctrees/tutorial-integration-testing.doctree and b/docs/build/doctrees/tutorial-integration-testing.doctree differ
diff --git a/docs/build/doctrees/tutorial-test-dsl.doctree b/docs/build/doctrees/tutorial-test-dsl.doctree
index 85b8dc2665..32f87c2f2e 100644
Binary files a/docs/build/doctrees/tutorial-test-dsl.doctree and b/docs/build/doctrees/tutorial-test-dsl.doctree differ
diff --git a/docs/build/doctrees/using-a-notary.doctree b/docs/build/doctrees/using-a-notary.doctree
index f70853b97e..bb0587e858 100644
Binary files a/docs/build/doctrees/using-a-notary.doctree and b/docs/build/doctrees/using-a-notary.doctree differ
diff --git a/docs/build/html/.buildinfo b/docs/build/html/.buildinfo
index c391c71a7b..48126ebbdf 100644
--- a/docs/build/html/.buildinfo
+++ b/docs/build/html/.buildinfo
@@ -1,4 +1,4 @@
# Sphinx build info version 1
# This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done.
-config: 81f5156b78c635dc74e3741102dbb51c
+config: 2535fde532a0ac1a7bd6c73ae772bf54
tags: 645f666f9bcd5a90fca523b33c5a78b7
diff --git a/docs/build/html/CLI-vs-IDE.html b/docs/build/html/CLI-vs-IDE.html
index c7fc329f7f..8260a94852 100644
--- a/docs/build/html/CLI-vs-IDE.html
+++ b/docs/build/html/CLI-vs-IDE.html
@@ -1,3 +1,7 @@
+
+
+
@@ -78,6 +82,11 @@
API reference
+
+Discourse Forums
+
+Slack
+
@@ -119,8 +128,9 @@
Gradle plugins for CorDapps
The CorDapp Template
Building the CorDapp template
-Running the Sample CorDapp
-Using the sample CorDapp
+Running the CorDapp template
+Interacting with the CorDapp template
+Extending the CorDapp template
The Corda node
Glossary
diff --git a/docs/build/html/_images/azure_vm_10_00_1.png b/docs/build/html/_images/azure_vm_10_00_1.png
new file mode 100644
index 0000000000..c073dd08e4
Binary files /dev/null and b/docs/build/html/_images/azure_vm_10_00_1.png differ
diff --git a/docs/build/html/_images/azure_vm_10_05_1.png b/docs/build/html/_images/azure_vm_10_05_1.png
new file mode 100644
index 0000000000..3d1396d46c
Binary files /dev/null and b/docs/build/html/_images/azure_vm_10_05_1.png differ
diff --git a/docs/build/html/_images/azure_vm_10_16_1.png b/docs/build/html/_images/azure_vm_10_16_1.png
new file mode 100644
index 0000000000..0786e08fc0
Binary files /dev/null and b/docs/build/html/_images/azure_vm_10_16_1.png differ
diff --git a/docs/build/html/_images/azure_vm_10_19.png b/docs/build/html/_images/azure_vm_10_19.png
new file mode 100644
index 0000000000..61bfc05f9a
Binary files /dev/null and b/docs/build/html/_images/azure_vm_10_19.png differ
diff --git a/docs/build/html/_images/azure_vm_10_20.png b/docs/build/html/_images/azure_vm_10_20.png
new file mode 100644
index 0000000000..5a0c72a5da
Binary files /dev/null and b/docs/build/html/_images/azure_vm_10_20.png differ
diff --git a/docs/build/html/_images/azure_vm_10_26.png b/docs/build/html/_images/azure_vm_10_26.png
new file mode 100644
index 0000000000..4ae9050dbd
Binary files /dev/null and b/docs/build/html/_images/azure_vm_10_26.png differ
diff --git a/docs/build/html/_images/azure_vm_10_47.png b/docs/build/html/_images/azure_vm_10_47.png
new file mode 100644
index 0000000000..f885924d8f
Binary files /dev/null and b/docs/build/html/_images/azure_vm_10_47.png differ
diff --git a/docs/build/html/_images/azure_vm_10_49.png b/docs/build/html/_images/azure_vm_10_49.png
new file mode 100644
index 0000000000..377e060cc5
Binary files /dev/null and b/docs/build/html/_images/azure_vm_10_49.png differ
diff --git a/docs/build/html/_images/azure_vm_10_51.png b/docs/build/html/_images/azure_vm_10_51.png
new file mode 100644
index 0000000000..549bd997d2
Binary files /dev/null and b/docs/build/html/_images/azure_vm_10_51.png differ
diff --git a/docs/build/html/_images/azure_vm_10_52.png b/docs/build/html/_images/azure_vm_10_52.png
new file mode 100644
index 0000000000..a36e1a1056
Binary files /dev/null and b/docs/build/html/_images/azure_vm_10_52.png differ
diff --git a/docs/build/html/_images/azure_vm_10_54.png b/docs/build/html/_images/azure_vm_10_54.png
new file mode 100644
index 0000000000..112cef6020
Binary files /dev/null and b/docs/build/html/_images/azure_vm_10_54.png differ
diff --git a/docs/build/html/_images/network.png b/docs/build/html/_images/network.png
index f72e90e985..565ae94a0d 100644
Binary files a/docs/build/html/_images/network.png and b/docs/build/html/_images/network.png differ
diff --git a/docs/build/html/_images/newTransactionCash.png b/docs/build/html/_images/newTransactionCash.png
new file mode 100644
index 0000000000..65a1028adb
Binary files /dev/null and b/docs/build/html/_images/newTransactionCash.png differ
diff --git a/docs/build/html/_images/newTransactionIssuer.png b/docs/build/html/_images/newTransactionIssuer.png
new file mode 100644
index 0000000000..1fbbe76699
Binary files /dev/null and b/docs/build/html/_images/newTransactionIssuer.png differ
diff --git a/docs/build/html/_images/vault.png b/docs/build/html/_images/vault.png
index d0f7210e02..d5db60e6b0 100644
Binary files a/docs/build/html/_images/vault.png and b/docs/build/html/_images/vault.png differ
diff --git a/docs/build/html/_sources/azure-vm.txt b/docs/build/html/_sources/azure-vm.txt
new file mode 100644
index 0000000000..a92448e405
--- /dev/null
+++ b/docs/build/html/_sources/azure-vm.txt
@@ -0,0 +1,175 @@
+Working with the Corda Demo on Azure Marketplace
+================================================
+
+Corda ships with a VM image which can be used to deploy a pre-configured virtual machine on the `Microsoft Azure Marketplace `_
+
+
+This Corda Demo VM is an easy option for running the demos; it is *NOT* a development environment. When you are ready to get developing on Corda and start making contributions to the project please clone the `GitHub Repos `_ instead.
+
+Pre-requisites
+--------------
+* Ensure you have a registered Microsoft Azure account and are logged on to the Azure portal.
+* It is recommended you generate a private-public SSH key pair (see `here `_)
+
+
+Deploying the VM
+----------------
+
+Search the Azure Marketplace for Corda.
+Click the 'Create' button.
+
+STEP 1: Basics
+
+* **Name**: Choose an appropriate descriptive name for the VM
+* **VM Disk Type**: Select 'SSD'
+* **Username**: Your preferred user name for the administrator account when accessing via SSH
+* **Authentication type**: Select 'SSH public key', then paste the contents of your SSH public key file (see pre-requisites, above) into the box below. Alternatively select 'Password' to use a password of your choice to administer the VM
+
+* **Subscription**: Select your subscription name
+* **Resource group**: Select 'Use existing'. From the drop-down menu, select your account group
+* **Location**: Select the geographical location physically closest to you
+
+.. image:: resources/azure_vm_10_00_1.png
+ :width: 300px
+
+Click 'OK'
+
+STEP 2: Size
+
+A range of available hardware configurations will be presented, along with estimated costs. For the purposes of running the demos, a configuration of 2 cores and at least 14GB is recommended
+
+.. image:: resources/azure_vm_10_05_1.png
+ :width: 300px
+
+Choose the required configuration and click 'Select'.
+
+STEP 3: Settings
+
+Adjust any configuration settings required. For the purposes of running the Corda demos, all settings may be left as default.
+
+.. image:: resources/azure_vm_10_16_1.png
+ :width: 300px
+
+STEP 4: Summary
+
+The banner at the top of the dialog should read 'Validation passed' otherwise go back and adjust settings where needed.
+
+.. image:: resources/azure_vm_10_19.png
+ :width: 300px
+
+Click 'OK' to proceed.
+
+STEP 5: Buy
+
+Click 'Purchase' to complete the configuration and start the VM deployment.
+
+The VM will begin the deployment process, which typically takes 4-5 minutes to complete. To see progress, click on the "Deploying" icon displayed.
+
+.. image:: resources/azure_vm_10_20.png
+ :width: 300px
+
+Once deployed, click 'Overview' to see the virtual machine details. Note down the **Public IP address**. You will need this to connect to the demo screens via your web browser:
+
+.. image:: resources/azure_vm_10_26.png
+ :width: 300px
+
+
+Viewing the SIMM Valuation demo
+-------------------------------
+The SIMM Valuation demo creates three nodes, representing three parties in the example workflow (Bank A, Bank B, Bank C). Each node listens on a different port - those used by the demo are:
+
+**SIMM Valuation Demo ports:** **12005 (node A for Bank A)**, **12007 (node B for Bank B)**, **12009 (node C for Bank C)**
+
+Open three browser tabs and direct each one to
+
+.. sourcecode:: shell
+
+ http://(public IP address):(port)/web/simmvaluationdemo
+
+specifying each of the three ports above in different windows, e.g.
+
+.. sourcecode:: shell
+
+ http://51.140.41.48/12005/web/simmvaluationdemo
+
+You will be able to view the basic web interface identifying the different banks.
+
+Now lets take a look at a transaction between Bank A and B which is not visible to Bank C. This illustrates the restricted data sharing feature of Corda, i.e. data is shared on a need-to-know basis. Nodes provide the dependency graph of a transaction they are sending to another node on demand, but there is no global broadcast of all transactions.
+
+1. In the browser tab for Bank A (the top right hand corner shows which bank you are administering) click 'Create New Trade' from the top navigation bar
+2. Select to trade with Bank B
+3. Select 'EUR Fixed 1y EURIBOR 3m' from the drop down
+4. Click 'Submit' to create the trade
+5. In the browser tab for Bank B click 'View Portfolio' from the top navigation bar to see this new trade
+6. In the browser tab for Bank C click 'View Portfolio' from the top navigation bar and you will not be able to see the trade, as expected
+
+.. image:: resources/azure_vm_10_51.png
+ :width: 300px
+
+.. note:: There is a known issue whereby some users may see a 400 error when navigating the SIMM Valuation demo. If you encounter this error, simply navigate back to the root page (http://*(public IP address)*:*(port)*/*web*/*simmvaluationdemo*) in the browser before continuing.
+
+Viewing the IRS demo
+--------------------
+The IRS demo creates three nodes: Bank A, Bank B and a node that runs a notary, a network map and an interest rates oracle together. 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. Each bank node listens on a different port - those used by the demo are:
+
+**IRS demo ports:** **11005 (node A for Bank A)**, **11007 (node B for Bank B)**
+
+Open two browser tabs and direct one to each of the following:
+
+.. sourcecode:: shell
+
+ http://localhost:11005/web/irsdemo
+ http://localhost:11007/web/irsdemo
+
+You will be able to see the the nodes' view of the ledger.
+
+.. image:: resources/azure_vm_10_52.png
+ :width: 300px
+
+Now lets take a look at how the interest rates oracle provides interest rates for a deal with a semi-annual payment frequency, and how the two counterparties to the trade see the same deal information on their own nodes, i.e. you see what I see.
+
+1. In the browser tab for Bank A click 'Create Deal' from the top navigation bar
+2. Modify the terms of the IRS deal, or leave as default
+3. Click 'Submit' to create the deal
+4. In the browser tab for Bank A click 'Recent Deals' from the top navigation bar to view the deal
+5. In the browser tab for Bank B click 'Recent Deals' from the top navigation bar to view the deal. Compare the economic details to those shown in the Bank A tab
+
+.. image:: resources/azure_vm_10_54.png
+ :width: 300px
+
+
+Viewing logs (advanced users)
+-----------------------------
+Users may wish to view the raw logs generated by each node, which contain more information about the operations performed by each node.
+
+You can access these using an SSH client of your choice (e.g. Putty) and logging into the virtual machine using the public IP address.
+Once logged in, navigate to
+
+.. sourcecode:: shell
+
+ /opt/simm-nodes/
+
+for the SIMM Valuation demo logs and
+
+.. sourcecode:: shell
+
+ /opt/irs-nodes/
+
+for the IRS demo logs.
+There are separate sub-directories for each of the three nodes (*nodea*, *nodeb*, *nodec*), each containing a */logs* sub-directory.
+
+The name of the log file will follow the name given to the service it reflects, e.g. *node-clint-vm-test.log*.
+
+.. image:: resources/azure_vm_10_47.png
+ :width: 300px
+
+You can open log files with any text editor.
+
+.. image:: resources/azure_vm_10_49.png
+ :width: 300px
+
+Next Steps
+----------
+Now you have taken a look at two Corda demos do go and visit the `dedicated Corda website `_
+
+Or to get straight into the Corda open source codebase, head over to the `Github Corda repo `_
diff --git a/docs/build/html/_sources/building-the-docs.txt b/docs/build/html/_sources/building-the-docs.txt
index 5d5677ee5d..769f09d465 100644
--- a/docs/build/html/_sources/building-the-docs.txt
+++ b/docs/build/html/_sources/building-the-docs.txt
@@ -20,7 +20,7 @@ script to find it, as in:
.. sourcecode:: shell
- r3prototyping/lib/dokka.jar
+ corda/lib/dokka.jar
Note that to install under OS X El Capitan, you will need to tell pip to install under ``/usr/local``, which can be
done by specifying the installation target on the command line:
diff --git a/docs/build/html/_sources/data-model.txt b/docs/build/html/_sources/data-model.txt
index da5319877d..b4fd05b58c 100644
--- a/docs/build/html/_sources/data-model.txt
+++ b/docs/build/html/_sources/data-model.txt
@@ -2,8 +2,7 @@ Data model
==========
This article covers the data model: how *states*, *transactions* and *code contracts* interact with each other and
-how they are represented in software. It doesn't attempt to give detailed design rationales or information on future
-design elements: please refer to the R3 wiki for background information.
+how they are represented in software.
Overview
--------
@@ -72,9 +71,7 @@ a special type of transaction is provided that moves a state (or set of states)
a mismatch. This is a future planned feature.
As the same terminology often crops up in different distributed ledger designs, let's compare this to other
-systems you may be familiar with. You can find more detailed design rationales for why the platform
-differs from existing systems in `the R3 wiki `_,
-but to summarise, the driving factors are:
+systems you may be familiar with. The key differences are:
* Improved contract flexibility vs Bitcoin
* Improved scalability vs Ethereum, as well as ability to keep parts of the transaction graph private (yet still uniquely addressable)
diff --git a/docs/build/html/_sources/flow-state-machines.txt b/docs/build/html/_sources/flow-state-machines.txt
index 1e3c3500d8..d14678f281 100644
--- a/docs/build/html/_sources/flow-state-machines.txt
+++ b/docs/build/html/_sources/flow-state-machines.txt
@@ -188,6 +188,8 @@ and try again.
.. note:: Java 9 is likely to remove this pre-marking requirement completely.
+.. note:: Accessing the vault from inside an @Suspendable function (e.g. via ``serviceHub.vaultService``) can cause a serialisation error when the fiber suspends. Instead, vault access should be performed from a helper non-suspendable function, which you then call from the @Suspendable function. We are working to fix this.
+
Starting your flow
------------------
@@ -505,4 +507,4 @@ the features we have planned:
* Being able to interact with people, either via some sort of external ticketing system, or email, or a custom UI.
For example to implement human transaction authorisations.
* A standard library of flows that can be easily sub-classed by local developers in order to integrate internal
- reporting logic, or anything else that might be required as part of a communications lifecycle.
\ No newline at end of file
+ reporting logic, or anything else that might be required as part of a communications lifecycle.
diff --git a/docs/build/html/_sources/getting-set-up.txt b/docs/build/html/_sources/getting-set-up.txt
index d4cd8cb4de..561def9c55 100644
--- a/docs/build/html/_sources/getting-set-up.txt
+++ b/docs/build/html/_sources/getting-set-up.txt
@@ -14,6 +14,10 @@ version of Java 8. The JDK can be obtained `from Oracle Update Project" in th
Troubleshooting
---------------
-See :doc:`getting-set-up-fault-finding`.
-
+See :doc:`getting-set-up-fault-finding`, or get in touch with us either on the `forums `_ or via `slack `_.
diff --git a/docs/build/html/_sources/index.txt b/docs/build/html/_sources/index.txt
index d6d98d2c93..74ab77e274 100644
--- a/docs/build/html/_sources/index.txt
+++ b/docs/build/html/_sources/index.txt
@@ -1,7 +1,7 @@
Welcome to the Corda documentation!
===================================
-.. warning:: This build of the docs is from the *master branch*, not a milestone release. It may not reflect the
+.. warning:: This build of the docs is from the "|version|" branch, not a milestone release. It may not reflect the
current state of the code. `Read the docs for M6 `_.
This is the developer guide for Corda, a proposed architecture for distributed ledgers. Here are the sources
@@ -107,6 +107,8 @@ Read on to learn:
release-notes
codestyle
building-the-docs
+ publishing-corda
+ azure-vm
.. toctree::
:maxdepth: 2
diff --git a/docs/build/html/_sources/messaging.txt b/docs/build/html/_sources/messaging.txt
index 91d7856d8b..a2139589ac 100644
--- a/docs/build/html/_sources/messaging.txt
+++ b/docs/build/html/_sources/messaging.txt
@@ -17,15 +17,6 @@ messaging subsystem directly. Instead you will build on top of the :doc:`flow fr
which adds a layer on top of raw messaging to manage multi-step flows and let you think in terms of identities
rather than specific network endpoints.
-Messaging types
----------------
-
-Every ``Message`` object has an associated *topic* and may have a *session ID*. These are wrapped in a ``TopicSession``.
-An implementation of ``MessagingService`` can be used to create messages and send them. You can get access to the
-messaging service via the ``ServiceHub`` object that is provided to your app. Endpoints on the network are
-identified at the lowest level using ``SingleMessageRecipient`` which may be e.g. an IP address, or in future
-versions perhaps a routing path through the network.
-
.. _network-map-service:
Network Map Service
@@ -48,4 +39,79 @@ The network map currently supports:
* Looking up node for a party
* Suggesting a node providing a specific service, based on suitability for a contract and parties, for example suggesting
an appropriate interest rates oracle for a interest rate swap contract. Currently no recommendation logic is in place.
- The code simply picks the first registered node that supports the required service.
\ No newline at end of file
+
+Message queues
+--------------
+
+The node makes use of various queues for its operation. The more important ones are described below. Others are used
+for maintenance and other minor purposes.
+
+:``p2p.inbound``:
+ The node listens for messages sent from other peer nodes on this queue. Only clients who are authenticated to be
+ nodes on the same network are given permission to send. Messages which are routed internally are also sent to this
+ queue (e.g. two flows on the same node communicating with each other).
+
+:``internal.peers.$identity``:
+ These are a set of private queues only available to the node which it uses to route messages destined to other peers.
+ The queue name ends in the base 58 encoding of the peer's identity key. There is at most one queue per peer. The broker
+ creates a bridge from this queue to the peer's ``p2p.inbound`` queue, using the network map service to lookup the
+ peer's network address.
+
+:``internal.services.$identity``:
+ These are private queues the node may use to route messages to services. The queue name ends in the base 58 encoding
+ of the service's owning identity key. There is at most one queue per service identity (but note that any one service
+ may have several identities). The broker creates bridges to all nodes in the network advertising the service in
+ question. When a session is initiated with a service counterparty the handshake is pushed onto this queue, and a
+ corresponding bridge is used to forward the message to an advertising peer's p2p queue. Once a peer is picked the
+ session continues on as normal.
+
+:``internal.networkmap``:
+ This is another private queue just for the node which functions in a similar manner to the ``internal.peers.*`` queues
+ except this is used to form a connection to the network map node. The node running the network map service is treated
+ differently as it provides information about the rest of the network.
+
+:``rpc.requests``:
+ RPC clients send their requests here, and it's only open for sending by clients authenticated as RPC users.
+
+:``clients.$user.rpc.$random``:
+ RPC clients are given permission to create a temporary queue incorporating their username (``$user``) and sole
+ permission to receive messages from it. RPC requests are required to include a random number (``$random``) from
+ which the node is able to construct the queue the user is listening on and send the response to that. This mechanism
+ prevents other users from being able listen in on the responses.
+
+Security
+--------
+
+Clients attempting to connect to the node's broker fall in one of four groups:
+
+#. Anyone connecting with the username ``SystemUsers/Node`` is treated as the node hosting the broker, or a logical
+ component of the node. The TLS certificate they provide must match the one broker has for the node. If that's the case
+ they are given full access to all valid queues, otherwise they are rejected.
+
+#. Anyone connecting with the username ``SystemUsers/Peer`` is treated as a peer on the same Corda network as the node. Their
+ TLS root CA must be the same as the node's root CA - the root CA is the doorman of the network and having the same root CA
+ implies we've been let in by the same doorman. If they are part of the same network then they are only given permission
+ to send to our ``p2p.inbound`` queue, otherwise they are rejected.
+
+#. Every other username is treated as a RPC user and authenticated against the node's list of valid RPC users. If that
+ is successful then they are only given sufficient permission to perform RPC, otherwise they are rejected.
+
+#. Clients connecting without a username and password are rejected.
+
+Artemis provides a feature of annotating each received message with the validated user. This allows the node's messaging
+service to provide authenticated messages to the rest of the system. For the first two client types described above the
+validated user is the X.500 subject DN of the client TLS certificate and we assume the common name is the legal name of
+the peer. This allows the flow framework to authentically determine the ``Party`` initiating a new flow. For RPC clients
+the validated user is the username itself and the RPC framework uses this to determine what permissions the user has.
+
+.. note:: ``Party`` lookup is currently done by the legal name which isn't guaranteed to be unique. A future version will
+ use the full X.500 name as it can provide additional structures for uniqueness.
+
+Messaging types
+---------------
+
+Every ``Message`` object has an associated *topic* and may have a *session ID*. These are wrapped in a ``TopicSession``.
+An implementation of ``MessagingService`` can be used to create messages and send them. You can get access to the
+messaging service via the ``ServiceHub`` object that is provided to your app. Endpoints on the network are
+identified at the lowest level using ``SingleMessageRecipient`` which may be e.g. an IP address, or in future
+versions perhaps a routing path through the network.
diff --git a/docs/build/html/_sources/node-explorer.txt b/docs/build/html/_sources/node-explorer.txt
index c1f88a41a6..dc27934393 100644
--- a/docs/build/html/_sources/node-explorer.txt
+++ b/docs/build/html/_sources/node-explorer.txt
@@ -1,8 +1,8 @@
Node Explorer
=============
-The node explorer provide views to the node's vault and transaction data using Corda's RPC framework.
-The user can execute cash transaction commands to issue and move cash to other party on the network or exit cash using the user interface.
+The node explorer provides views into a node's vault and transaction data using Corda's RPC framework.
+The user can execute cash transaction commands to issue and move cash to other parties on the network or exit cash (eg. remove from the ledger)
Running the UI
--------------
@@ -17,6 +17,27 @@ Running the UI
Running demo nodes
------------------
+
+A demonstration Corda network topology is configured with 5 nodes playing the following roles:
+
+1. Notary
+2. Issuer nodes, representing two fictional central banks (UK Bank Plc issuer of GBP and USA Bank Corp issuer of USD)
+3. Participant nodes, representing two users (Alice and Bob)
+
+When connected to an *Issuer* node, a user can execute cash transaction commands to issue and move cash to itself or other
+parties on the network or to exit cash (for itself only).
+
+When connected to a *Participant* node a user can only execute cash transaction commands to move cash to other parties on the network.
+
+The Demo Nodes can be started in one of two modes:
+
+1. Normal
+
+ Fresh clean environment empty of transactions.
+ Firstly, launch an Explorer instance to login to one of the Issuer nodes and issue some cash to the other participants (Bob and Alice).
+ Then launch another Explorer instance to login to a participant node and start making payments (eg. move cash).
+ You will only be able to exit (eg. redeem from the ledger) cash as an issuer node.
+
**Windows**::
gradlew.bat tools:explorer:runDemoNodes
@@ -25,21 +46,45 @@ Running demo nodes
./gradlew tools:explorer:runDemoNodes
-.. note:: 3 Corda nodes will be created on the following port on localhost by default.
+2. Simulation
+
+ In this mode Nodes will automatically commence executing commands as part of a random generation process.
+ Issuer nodes will randomly issue, move and exit cash.
+ Participant nodes will randomly generate spends (eg. move cash to other nodes, including issuers)
+
+**Windows**::
+
+ gradlew.bat tools:explorer:runSimulationNodes
+
+**Other**::
+
+ ./gradlew tools:explorer:runSimulationNodes
+
+
+.. note:: 5 Corda nodes will be created on the following port on localhost by default.
* Notary -> 20002
* Alice -> 20004
* Bob -> 20006
+ * UK Bank Plc -> 20008 (*Issuer node*)
+ * USA Bank Corp -> 20010 (*Issuer node*)
+
+Explorer login credentials to the Issuer nodes are defaulted to ``manager`` and ``test``.
+Explorer login credentials to the Participants nodes are defaulted to ``user1`` and ``test``.
+Please note you are not allowed to connect to the notary.
+
+.. note:: Alternatively, you may start the demo nodes from within IntelliJ using either of the run configurations
+ ``Explorer - demo nodes`` or ``Explorer - demo nodes (simulation)``
+
+.. note:: Use the Explorer in conjunction with the Trader Demo and Bank of Corda samples to use other *Issuer* nodes.
Interface
---------
Login
User can login to any Corda node using the explorer. Alternatively, ``gradlew explorer:runDemoNodes`` can be used to start up demo nodes for testing.
Corda node address, username and password are required for login, the address is defaulted to localhost:0 if leave blank.
- Username and password can be configured via the ``rpcUsers`` field in node's configuration file; for demo nodes, it is defaulted to ``user1`` and ``test``.
+ Username and password can be configured via the ``rpcUsers`` field in node's configuration file.
-.. note:: If you are connecting to the demo nodes, only Alice and Bob (20004, 20006) are accessible using user1 credential, you won't be able to connect to the notary.
-
.. image:: resources/explorer/login.png
:scale: 50 %
:align: center
@@ -57,12 +102,19 @@ Cash
.. image:: resources/explorer/vault.png
-New cash transaction
- This is where you can create new cash transactions.
- The user can choose from three transaction types (issue, pay and exit) and any party visible on the network.
+New Transactions
+ This is where you can create new cash transactions.
+ The user can choose from three transaction types (issue, pay and exit) and any party visible on the network.
+
+ General nodes can only execute pay commands to any other party on the network.
+
+.. image:: resources/explorer/newTransactionCash.png
+
+Issuer Nodes
+ Issuer nodes can execute issue (to itself or to any other party), pay and exit transactions.
The result of the transaction will be visible in the transaction screen when executed.
-.. image:: resources/explorer/newTransaction.png
+.. image:: resources/explorer/newTransactionIssuer.png
Transactions
The transaction view contains all transactions handled by the node in a table view. It shows basic information on the table e.g. Transaction ID,
diff --git a/docs/build/html/_sources/permissioning.txt b/docs/build/html/_sources/permissioning.txt
index 5fea5c539e..721f2a33fe 100644
--- a/docs/build/html/_sources/permissioning.txt
+++ b/docs/build/html/_sources/permissioning.txt
@@ -2,12 +2,15 @@ Network permissioning
=====================
The keystore located in ``/certificates/sslkeystore.jks`` is required to connect to the Corda network securely.
-In development mode (when ``devMode = true``, see :doc:`corda-configuration-file` for more information) a pre-configured keystore will be used if the keystore does not exist.
-This is to ensure developers can get the nodes working as quickly as possible.
+In development mode (when ``devMode = true``, see :doc:`corda-configuration-file` for more information) a pre-configured
+keystore will be used if the keystore does not exist. This is to ensure developers can get the nodes working as quickly
+as possible.
-However this is not secure for the real network. This documentation will explain the procedure of obtaining a signed certificate for TestNet.
+However this is not secure for the real network. This documentation will explain the procedure of obtaining a signed
+certificate for TestNet.
-.. warning:: The TestNet has not been setup yet as of Milestone 6 release. You will not be able to connect to the certificate signing server.
+.. warning:: The TestNet has not been setup yet as of Milestone 6 release. You will not be able to connect to the
+ certificate signing server.
Certificate signing request utility
-----------------------------------
@@ -15,13 +18,19 @@ Certificate signing request utility
The utility creates certificate signing request based on node information obtained from the node configuration.
The following information from the node configuration file is needed to generate a certificate signing request.
-:myLegalName: Your company's legal name. e.g. "R3 CEV, LLC"
+:myLegalName: Your company's legal name. e.g. "Mega Corp LLC". This needs to be unique on the network. If another node
+ has already been permissioned with this name then the permissioning server will automatically reject the request. The
+ request will also be rejected if the name contains a ``=`` or ``,``.
-:nearestCity: e.g. "London"
+ .. note:: In a future version the uniquess requirement will be relaxed to a X.500 name. This will allow differentiation
+ between entities with the same name.
+
+:nearestCity: e.g. "London"
:emailAddress: e.g. "admin@company.com"
-:certificateSigningService: Certificate signing server URL. A certificate signing server will be hosted by R3 in the near future. e.g."https://testnet.certificate.corda.net"
+:certificateSigningService: Certificate signing server URL. A certificate signing server will be hosted by R3 in the near
+ future. e.g."https://testnet.certificate.corda.net"
A new pair of private and public keys will be generated by the utility and will be used to create the request.
@@ -34,18 +43,18 @@ This process only needs to be done once when the node connects to the network fo
Building the utility
--------------------
-The utility will be created as part of the main build ``buildCordaJAR``.
+The utility will be created as part of the gradle ``:node`` module ``buildCordaJAR`` task.
You can also build the utility JAR by run the following command from the Corda project root directory.
**Windows**::
- gradlew.bat buildCertSigningRequestUtilityJAR
+ gradlew.bat :node:buildCertSigningRequestUtilityJAR
**Other**::
- ./gradlew buildCertSigningRequestUtilityJAR
+ ./gradlew :node:buildCertSigningRequestUtilityJAR
-The utility JAR will be created in ``/build/libs/certSigningRequestUtility.jar``
+The utility JAR will be created in ``/node/build/libs/certSigningRequestUtility.jar``
Running the utility
diff --git a/docs/build/html/_sources/publishing-corda.txt b/docs/build/html/_sources/publishing-corda.txt
new file mode 100644
index 0000000000..ab04bcf3e9
--- /dev/null
+++ b/docs/build/html/_sources/publishing-corda.txt
@@ -0,0 +1,76 @@
+Publishing Corda
+================
+
+Before Publishing
+-----------------
+
+Before publishing you must make sure the version you plan to publish has a unique version number. Jcenter and Maven
+Central will not allow overwriting old versions _unless_ the version is a snapshot.
+
+This guide assumes you are trying to publish to net.corda.*. Any other Maven coordinates require approval from Jcenter
+and Maven Central.
+
+Publishing Locally
+------------------
+
+To publish the codebase locally to Maven Local you must run:
+
+.. code-block:: text
+
+ gradlew install
+
+.. note:: This command is an alias for `publishToMavenLocal`.
+
+Publishing to Jcenter
+---------------------
+
+.. note:: The module you wish to publish must be linked to jcenter in bintray. Only the founding account can do this.
+
+To publish to Jcenter you must first have the following;
+
+1. An account on bintray in the R3 organisation
+2. Our GPG key's passphrase for signing the binaries to publish
+
+Getting Setup
+`````````````
+
+You must now set the following environment variables:
+
+* CORDA_BINTRAY_USER your Bintray username
+* CORDA_BINTRAY_KEY to your bintray API key (found at: https://bintray.com/profile/edit)
+* CORDA_BINTRAY_GPG_PASSPHRASE to our GPG passphrase
+
+Publishing
+``````````
+
+Once you are setup you can upload all modules in a project with
+
+.. code-block:: text
+
+ gradlew bintrayUpload
+
+Now login to Bintray and navigate to the corda repository, you will see a box stating you have published N files
+and asking if you wish to publish. You can now publish to Bintray and Jcenter by clicking this button.
+
+.. warning:: Before publishing you should check that all of the files are uploaded and are signed.
+
+Within a minute your new version will be available to download and use.
+
+Publishing to Maven Central
+---------------------------
+
+To publish to Maven Central you need the following;
+
+1. An admin account on our Bintray R3 organisation
+2. A published version in Bintray
+3. An account with our Sonatype organisation (Maven Central's host)
+
+Publishing
+``````````
+
+1. Publish to Bintray
+2. Navigate to the project you wish to publish
+3. Click "Maven Central"
+4. Enter your Sonatype credentials to publish a new version
+
+.. note:: The project you publish must be already published to Bintray and the project must be linked to Jcenter
\ No newline at end of file
diff --git a/docs/build/html/_sources/running-the-demos.txt b/docs/build/html/_sources/running-the-demos.txt
index a1a3939591..193520a98f 100644
--- a/docs/build/html/_sources/running-the-demos.txt
+++ b/docs/build/html/_sources/running-the-demos.txt
@@ -13,6 +13,8 @@ so far. We have:
5. The SIMM valuation demo, a large demo which shows two nodes agreeing on a portfolio and valuing the initial margin
using the Standard Initial Margin Model.
6. The distributed notary demo, which demonstrates a single node getting multiple transactions notarised by a distributed (Raft-based) notary.
+7. The Bank of Corda demo, which demonstrates a node acting as an issuer of assets (the Bank of Corda) and remote client
+ applications requesting issuance (via RPC, HTTP) of some cash on behalf of a node called Big Corporation.
.. note:: If any demos don't work please jump on our mailing list and let us know.
@@ -29,15 +31,15 @@ develop the demos themselves. For more details about running via the command lin
Trader demo
-----------
-This demo brings up three nodes: Bank A, Bank B and a notary/network map node that they both use. Bank A will
-be the buyer, and self-issues some cash in order to acquire commercial paper from Bank B, the seller.
+This demo brings up four nodes: Bank A, Bank B, Bank Of Corda and a notary/network map node that they both 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:
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`` (or ``runnodes.bat`` on Windows) to open up three new terminals with the three nodes.
-3. Run ``./gradlew samples:trader-demo:runBuyer`` to set up the buyer node with some self-issued cash. This step
- is not expected to print much.
+2. Run ``./samples/trader-demo/build/nodes/runnodes`` (or ``runnodes.bat`` on Windows) to open up four new terminals with the four nodes.
+3. Run ``./gradlew samples:trader-demo:runBuyer`` to instruct the buyer node to request issuance of some cash from the Bank of Corda node.
+ This step will display progress information related to the cash issuance process (in the bank of corda node log output).
4. Run ``./gradlew samples:trader-demo:runSeller`` to trigger the transaction. You can see both sides of the
trade print their progress and final transaction state in the bank node tabs/windows.
@@ -156,6 +158,63 @@ by using the H2 web console:
- The committed states are stored in the ``NOTARY_COMMITTED_STATES`` table. Note that the raw data is not human-readable,
but we're only interested in the row count for this 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 the "Bitcoin faucet", that used to dispense free bitcoins to developers for
+ testing and experimentation purposes.
+
+To run from the command line (recommended for Mac/UNIX users!):
+
+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.
+
+.. note:: to verify the Bank of Corda node is alive and running navigate to the following URL
+ http://localhost:10005/api/bank/date
+
+.. note:: the Bank of Corda node explicitly advertises with a node service type as follows:
+ ``advertisedServices = setOf(ServiceInfo(ServiceType.corda.getSubType("issuer"))))``
+ This allows for 3rd party applications to perform actions based on Node Type.
+ For example, the Explorer tool only allows nodes of this type to issue and exit cash.
+
+3. Run ``./gradlew samples:bank-of-corda-demo:runRPCCashIssue`` in another terminal window to trigger a cash issuance request
+4. Run ``./gradlew samples:bank-of-corda-demo:runWebCashIssue`` in another terminal window to trigger another cash issuance request
+ Now look at the other windows to see the output of the demo.
+
+Or you can run them from inside IntelliJ as follows:
+
+1. Open the Corda project in IntelliJ and run the "Install" configuration
+2. Open the Corda samples project in IntelliJ and run the "Bank Of Corda Demo: Run Issuer" configuration
+3. Run "Bank Of Corda Demo: Run RPC Cash Issue" - requests issuance of some cash on behalf of Big Corporation via RPC
+4. Run "Bank Of Corda Demo: Run Web Cash Issue" - requests issuance of some cash on behalf of Big Corporation via HTTP
+
+In the "Bank Of Corda Demo: Run Issuer" window you should see the following information lines displayed:
+
+- Awaiting issuance request
+- Self issuing asset
+- Transferring asset to issuance requester
+- Confirming asset issuance to requester
+
+In the the client issue request window you should see the following printed:
+
+- Successfully processed Cash Issue request
+
+Launch the Explorer application to visualize the issuance and transfer of cash on each node:
+
+ ``./gradlew tools:explorer:run``
+
+And use the following logon details:
+
+- for the Bank of Corda node specify localhost, port 10004, username user1, password test
+- for the Big Corporation node specify localhost, port 10006, username user1, password test
+
+See https://docs.corda.net/node-explorer.html for further details on usage.
+
SIMM and Portfolio Demo - aka the Initial Margin Agreement Demo
---------------------------------------------------------------
diff --git a/docs/build/html/_sources/setting-up-a-corda-network.txt b/docs/build/html/_sources/setting-up-a-corda-network.txt
index 6e5df38a77..e6b3ae3180 100644
--- a/docs/build/html/_sources/setting-up-a-corda-network.txt
+++ b/docs/build/html/_sources/setting-up-a-corda-network.txt
@@ -20,13 +20,8 @@ Setting up your own network
Certificates
------------
-If two nodes are to communicate successfully then both need to have
-each other's root certificate in their truststores. The simplest way
-to achieve this is to have all nodes sign off of a single root.
-
-Later R3 will provide this root for production use, but for testing you
-can use ``certSigningRequestUtility.jar`` to generate a node
-certificate with a fixed test root:
+All nodes belonging to the same Corda network must have the same root CA. For testing purposes you can
+use ``certSigningRequestUtility.jar`` to generate a node certificate with a fixed test root:
.. sourcecode:: bash
diff --git a/docs/build/html/_sources/tutorial-cordapp.txt b/docs/build/html/_sources/tutorial-cordapp.txt
index 2097ac4267..2c82adf187 100644
--- a/docs/build/html/_sources/tutorial-cordapp.txt
+++ b/docs/build/html/_sources/tutorial-cordapp.txt
@@ -22,6 +22,25 @@ We recommend you read the non-technical white paper and technical white paper be
intended design from beginning to end. It is the kind of document that you should read, or at least, read parts of. Note
that because the technical white paper describes the intended end state, it does not always align with the implementation.
+Background
+----------
+
+The Example CorDapp implements a basic scenario where a buyer wishes to submit purchase orders to a seller. The scenario
+defines four nodes:
+
+* **Controller** which hosts the network map service and validating notary service.
+* **NodeA** who is the buyer.
+* **NodeB** who is the seller.
+* **NodeC** an unrelated third party.
+
+NodeA can generate purchase orders for lists and quantities of items and associated metadata such as delivery address
+and delivery date. The flows used to facilitate the agreement process always results in an agreement with the seller as
+long as the purchase order meets the contract constraints which are defined in ``PurchaseOrderContract.kt``.
+
+All agreed purchase orders between NodeA and NodeB become "shared facts" between NodeA and NodeB. But note that NodeC
+won't see any of these transactions or have copies of any of the resulting ``PurchaseOrderState`` objects. This is
+because data is only propagated on a need-to-know basis.
+
Getting started
---------------
@@ -201,14 +220,14 @@ Next, IntelliJ will show a bunch of pop-up windows. One of which requires our at
.. image:: resources/unlinked-gradle-project.png
:width: 400
-Click the 'import gradle project' link. A dialogue will pop-up. Press OK. Gradle will now begin obtianing all the
+Click the 'import gradle project' link. A dialogue will pop-up. Press OK. Gradle will now obtain all the
project dependencies and perform some indexing. It usually takes a minute or so. If you miss the 'import gradle project'
dialogue, simply close and re-open IntelliJ again to see it again.
**Alternative approach**
Alternatively, one can instruct IntelliJ to create a new project through cloning a repository. From the IntelliJ welcome
-dialogue (shown above), opt to 'check out from version control', then select git and enter the git url for the CorDpp tempalte
+dialogue (shown above), opt to 'check out from version control', then select git and enter the git URL for the CorDapp template
(https://github.com/corda/cordapp-template). You'll then need to import the Gradle project when prompted, as explained above.
**If you already have IntelliJ open**
@@ -245,14 +264,18 @@ Unix/Mac OSX: ``./gradlew deployNodes``
Windows: ``gradlew.bat deployNodes``
-Building straight away will build the example CorDapp defined the the CorDapp template source. For more information on the example
-CorDapp see "The Example CorDapp" section below. Gradle will then grab all the dependencies for you and build the
-example CorDapp.
+This build process will build the example CorDapp defined in the CorDapp template source. CorDapps can be written in
+any language targeting the JVM. In our case, we've provided the template source in both Kotlin (``/kotlin/src``) and
+Java (``/java/src``) Since both sets of source files are functionally identical, we will refer to the Kotlin build
+throughout the documentation.
+
+For more information on the example CorDapp see "The Example CorDapp" section below. Gradle will then grab all the
+dependencies for you and build the example CorDapp.
The ``deployNodes`` Gradle task allows you easily create a formation of Corda nodes. In the case of the example CorDapp
we are creating ``four`` nodes.
-After the building process has finished to see the newly built nodes, you can navigate to the ``/build/nodes`` folder
+After the building process has finished to see the newly built nodes, you can navigate to the ``kotlin/build/nodes`` folder
located in the ``cordapp-template`` root directory. You can ignore the other folders in ``/build`` for now. The ``nodes``
folder has the following structure:
@@ -294,13 +317,13 @@ Open the Gradle window by selecting ``View > Tool windows > Gradle`` from the ma
open on the right hand side of the IDE. Expand `tasks` and then expand `other`. Double click on `deployNodes`. Gradle will
start the build process and output progress to a console window in the IDE.
-Running the Sample CorDapp
-==========================
+Running the CorDapp template
+============================
-Running the Sample CorDapp from the command line
-------------------------------------------------
+Running the CorDapp template from the command line
+--------------------------------------------------
-To run the sample CorDapp navigate to the ``build/nodes`` folder and execute the ``runnodes`` shell script with:
+To run the sample CorDapp navigate to the ``kotlin/build/nodes`` folder and execute the ``runnodes`` shell script with:
Unix: ``./runnodes`` or ``sh runnodes``
@@ -319,8 +342,8 @@ message and some pertinent config information, see below:
--- DEVELOPER SNAPSHOT ------------------------------------------------------------
- Logs can be found in : /Users/rogerwillis/Documents/Corda/cordapp-template/build/nodes/nodea/logs
- Database connection url is : jdbc:h2:tcp://10.18.0.196:50661/node
+ Logs can be found in : /Users/rogerwillis/Documents/Corda/cordapp-template/kotlin/build/nodes/nodea/logs
+ Database connection URL is : jdbc:h2:tcp://10.18.0.196:50661/node
Node listening on address : localhost:10004
Loaded plugins : com.example.plugin.ExamplePlugin
Embedded web server is listening on : http://10.18.0.196:10005/
@@ -368,7 +391,7 @@ Running CorDapps on separate machines
Corda nodes can be run on separate machines with little additional configuration to the above instructions.
When you have successfully run the ``deployNodes`` gradle task, choose which nodes you would like to run on separate
-machines. Copy the folders for those nodes from ``build/nodes`` to the other machines. Make sure that you set the
+machines. Copy the folders for those nodes from ``kotlin/build/nodes`` to the other machines. Make sure that you set the
``networkMapAddress`` property in ``node.conf`` to the correct hostname:port where the network map service node is
hosted.
@@ -405,36 +428,17 @@ To stop the nodes, press the red "stop" button at the top right-hand side of the
The node driver can also be used to as a basis for `debugging your CorDapp`_
-Using the sample CorDapp
-========================
+Interacting with the CorDapp template
+=====================================
-Background
-----------
-
-The Example CorDapp implements a basic scenario where a buyer wishes to submit purchase orders to a seller. The scenario
-defines four nodes:
-
-* **Controller** which hosts the network map service and validating notary service.
-* **NodeA** who is the buyer.
-* **NodeB** who is the seller.
-* **NodeC** an unrelated third party.
-
-NodeA can generate purchase orders for lists and quantities of items and associated metadata such as delivery address
-and delivery date. The flows used to facilitate the agreement process always results in an agreement with the seller as
-long as the purchase order meets the contract constraints which are defined in ``PurchaseOrderContract.kt``.
-
-All agreed purchase orders between NodeA and NodeB become "shared facts" between NodeA and NodeB. But note that NodeC
-won't see any of these transactions or have copies of any of the resulting ``PurchaseOrderState`` objects. This is
-because data is only propagated on a need-to-know basis.
-
-Interfaces
-----------
+Via HTTP
+--------
The CorDapp defines a few HTTP API end-points and also serves some static web content. The end-points allow you to
list purchase orders and add purchase orders.
The nodes can be found using the following port numbers, defined in build.gradle and the respective node.conf file for
-each node found in `build/nodes/NodeX`` etc:
+each node found in `kotlin/build/nodes/NodeX`` etc:
* Controller: ``localhost:10003``
* NodeA: ``localhost:10005``
@@ -465,7 +469,7 @@ To create a purchase order from NodeA to NodeB, use:
.. sourcecode:: bash
- echo '{"orderNumber": "1","deliveryDate": "2018-09-15","deliveryAddress": {"city": "London","country": "UK"},"items" : [{"name": "widget","amount": "3"},{"name": "thing","amount": "4"}]}' | curl -T - -H 'Content-Type: application/json' http://localhost:10005/api/example/NodeB/create-purchase-order
+ echo '{"orderNumber": "1","deliveryDate": "2018-09-15","deliveryAddress": {"city": "London","country": "UK"},"items" : [{"name": "widget","amount": "3"},{"name": "thing","amount": "4"}]}' | cURL -T - -H 'Content-Type: application/json' http://localhost:10005/api/example/NodeB/create-purchase-order
Note the port number ``10005`` (NodeA) and NodeB referenced in the API end-point path. This command instructs NodeA to
create and send a purchase order to NodeB. Upon verification and completion of the process, both nodes (but not NodeC) will
@@ -550,7 +554,8 @@ navigate to http://localhost:10007/api/example/purchase-orders.
Navigate to http://localhost:10005/web/example the refresh button in the top left-hand side of the page. You should
see the newly created agreement on the page.
-**Accessing the h2 database via h2 web console:**
+Using the h2 web console
+------------------------
You can connect to the h2 database to see the current state of the ledger, among other data such as the current state of
the network map cache. Firstly, navigate to the folder where you downloaded the h2 web console as part of the pre-requisites
@@ -572,13 +577,14 @@ The h2 web console should start up in a web browser tab. To connect we first nee
node outputs its connection string in the terminal window as it starts up. In a terminal window where a node is running,
look for the following string:
-``Database connection url is : jdbc:h2:tcp://10.18.0.150:56736/node``
+``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 in to 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.
-**Using the Example RPC client:**
+Using the Example RPC client
+----------------------------
The ``/src/main/kotlin/com/example/client/ExampleClientRPC.kt`` file is a simple utility which uses the client RPC library
to connect to a node and log the 'placed' purchase orders. It will log any existing purchase orders and listen for any future
@@ -606,6 +612,9 @@ application see:
* :doc:`Client RPC documentation `
* :doc:`Client RPC tutorial `
+Extending the CorDapp template
+==============================
+
CorDapp-template Project Structure
----------------------------------
@@ -627,48 +636,90 @@ The CorDapp template has the following directory structure:
├── lib
│  ├── ...
├── settings.gradle
- └── src
- ├── main
-   │  ├── java
-   │  ├── kotlin
-   │  │  └── com
-   │  │  └── example
-   │  │  ├── Main.kt
-   │  │  ├── api
-   │  │  │  └── ExampleApi.kt
-   │  │  ├── client
-   │  │  │  └── ExampleClientRPC.kt
-   │  │  ├── contract
-   │  │  │  ├── PurchaseOrderContract.kt
-   │  │  │  └── PurchaseOrderState.kt
-   │  │  ├── model
-   │  │  │  └── PurchaseOrder.kt
-   │  │  ├── plugin
-   │  │  │  └── ExamplePlugin.kt
-   │  │  └── flow
-   │  │  └── ExampleFlow.kt
-   │  │  └── service
-   │  │  └── ExampleService.kt
- │  ├── python
- │  └── resources
- │  ├── META-INF
- │  │  └── services
- │  │  └── net.corda.core.node.CordaPluginRegistry
- │  ├── certificates
- │  │  ├── readme.txt
- │  │  ├── sslkeystore.jks
- │  │  └── truststore.jks
- │  └── exampleWeb
- │  ├── index.html
- │  └── js
- │  └── example.js
- └── test
- ├── java
- ├── kotlin
- │  └── com
- │  └── example
- │  └── ExampleTest.kt
-   └── resources
+ ├── kotlin
+ │ └── src
+ │ ├── main
+ │   │  ├── kotlin
+ │   │  │  └── com
+ │   │  │  └── example
+ │   │  │  ├── Main.kt
+ │   │  │  ├── api
+ │   │  │  │  └── ExampleApi.kt
+ │   │  │  ├── client
+ │   │  │  │  └── ExampleClientRPC.kt
+ │   │  │  ├── contract
+ │   │  │  │  ├── PurchaseOrderContract.kt
+ │   │  │  │  └── PurchaseOrderState.kt
+ │   │  │  ├── model
+ │   │  │  │  └── PurchaseOrder.kt
+ │   │  │  ├── plugin
+ │   │  │  │  └── ExamplePlugin.kt
+ │   │  │  └── flow
+ │   │  │  └── ExampleFlow.kt
+ │   │  │  └── service
+ │   │  │  └── ExampleService.kt
+ │ │  ├── python
+ │ │  └── resources
+ │ │  ├── META-INF
+ │ │  │  └── services
+ │ │  │  └── net.corda.core.node.CordaPluginRegistry
+ │ │  ├── certificates
+ │ │  │  ├── readme.txt
+ │ │  │  ├── sslkeystore.jks
+ │ │  │  └── truststore.jks
+ │ │  └── exampleWeb
+ │ │  ├── index.html
+ │ │  └── js
+ │ │  └── example.js
+ │ └── test
+ │ ├── java
+ │ ├── kotlin
+ │ │  └── com
+ │ │  └── example
+ │ │  └── ExampleTest.kt
+ │   └── resources
+ └── java
+ └── src
+ ├── main
+   │  ├── java
+   │  │  └── com
+   │  │  └── example
+   │  │  ├── Main.java
+   │  │  ├── api
+   │  │  │  └── ExampleApi.java
+   │  │  ├── client
+   │  │  │  └── ExampleClientRPC.java
+   │  │  ├── contract
+   │  │  │  ├── PurchaseOrderContract.java
+   │  │  │  └── PurchaseOrderState.java
+   │  │  ├── model
+   │  │  │  └── PurchaseOrder.java
+   │  │  ├── plugin
+   │  │  │  └── ExamplePlugin.java
+   │  │  └── flow
+   │  │  └── ExampleFlow.java
+   │  │  └── service
+   │  │  └── ExampleService.java
+ │  ├── python
+ │  └── resources
+ │  ├── META-INF
+ │  │  └── services
+ │  │  └── net.corda.core.node.CordaPluginRegistry
+ │  ├── certificates
+ │  │  ├── readme.txt
+ │  │  ├── sslkeystore.jks
+ │  │  └── truststore.jks
+ │  └── exampleWeb
+ │  ├── index.html
+ │  └── js
+ │  └── example.js
+ └── test
+ ├── java
+ ├── kotlin
+ │  └── com
+ │  └── example
+ │  └── ExampleTest.kt
+   └── resources
In the file structure above, the most important files and directories to note are:
@@ -677,15 +728,18 @@ In the file structure above, the most important files and directories to note ar
* **gradle** contains the gradle wrapper, which allows the use of Gradle without installing it yourself and worrying
about which version is required.
* **lib** contains the Quasar.jar which is required for runtime instrumentation of classes by Quasar.
-* **src/main/kotlin** contains the source code for the example CorDapp.
-* **src/main/python** contains a python script which accesses nodes via RPC.
-* **src/main/resources** contains the certificate store, some static web content to be served by the nodes and the
- PluginServiceRegistry file.
-* **src/test/kotlin** contains unit tests for protocols, contracts, etc.
+* **kotlin** contains the source code for the example CorDapp written in Kotlin.
+ * **kotlin/src/main/kotlin** contains the source code for the example CorDapp.
+ * **kotlin/src/main/python** contains a python script which accesses nodes via RPC.
+ * **kotlin/src/main/resources** contains the certificate store, some static web content to be served by the nodes and the
+ PluginServiceRegistry file.
+ * **kotlin/src/test/kotlin** contains unit tests for protocols, contracts, etc.
+* **java** contains the same source code, but written in java. This is an aid for users who do not want to develop in
+ Kotlin, and serves as an example of how CorDapps can be developed in any language targeting the JVM.
Some elements are covered in more detail below.
-The build.gradle File
+The build.gradle file
---------------------
It is usually necessary to make a couple of changes to the ``build.gradle`` file. Here will cover the most pertinent bits.
@@ -758,7 +812,7 @@ like to deploy for testing. See further details below:
.. sourcecode:: groovy
task deployNodes(type: com.r3corda.plugins.Cordform, dependsOn: ['build']) {
- directory "./build/nodes" // The output directory.
+ directory "./kotlin/build/nodes" // The output directory.
networkMap "Controller" // The artemis address of the node to be used as the network map.
node {
name "Controller" // Artemis name of node to be deployed.
@@ -804,7 +858,7 @@ Re-Deploying Your Nodes Locally
If you need to create any additional nodes you can do it via the ``build.gradle`` file as discussed above in
``the build.gradle file`` and in more detail in the "cordFormation" section.
-You may also wish to edit the ``/build/nodes//node.conf`` files for your nodes. For more information on
+You may also wish to edit the ``/kotlin/build/nodes//node.conf`` files for your nodes. For more information on
doing this, see the :doc:`Corda configuration file ` page.
Once you have made some changes to your CorDapp you can redeploy it with the following command:
@@ -813,6 +867,39 @@ Unix/Mac OSX: ``./gradlew deployNodes``
Windows: ``gradlew.bat deployNodes``
+Running Nodes Across Machines
+-----------------------------
+
+The nodes can also be set up to communicate between separate machines on the
+same subnet.
+
+After deploying the nodes, navigate to the build folder (`kotlin/build/
+nodes` or `java/build/nodes`) and move some of the individual node folders to
+separate machines on the same subnet (e.g. using a USB key). It is important
+that no nodes - including the controller node - end up on more than one
+machine. Each computer should also have a copy of `runnodes` and
+`runnodes.bat`.
+
+For example, you may end up with the following layout:
+
+* Machine 1: `controller`, `nodea`, `runnodes`, `runnodes.bat`
+* Machine 2: `nodeb`, `nodec`, `runnodes`, `runnodes.bat`
+
+You must now edit the configuration file for each node, including the
+controller. Open each node's config file (`[nodeName]/node.conf`), and make
+the following changes:
+
+* Change the artemis address to the machine's ip address (e.g.
+`artemisAddress="10.18.0.166:10006"`)
+* Change the network map address to the ip address of the machine where the
+controller node is running (e.g. `networkMapAddress="10.18.0.166:10002"`)
+(please note that the controller will not have a network map address)
+
+Each machine should now run its nodes using `runnodes` or `runnodes.bat`
+files. Once they are up and running, the nodes should be able to place
+purchase orders among themselves in the same way as when they were running on
+the same machine.
+
Debugging your CorDapp
----------------------
diff --git a/docs/build/html/_sources/tutorial-test-dsl.txt b/docs/build/html/_sources/tutorial-test-dsl.txt
index 9df0c146af..6e6d98c9ab 100644
--- a/docs/build/html/_sources/tutorial-test-dsl.txt
+++ b/docs/build/html/_sources/tutorial-test-dsl.txt
@@ -1,6 +1,6 @@
.. highlight:: kotlin
.. role:: kotlin(code)
- :language: kotlin
+ :language: kotlin
.. raw:: html
@@ -10,7 +10,7 @@
Writing a contract test
=======================
-This tutorial will take you through the steps required to write a contract test using Kotlin and/or Java.
+This tutorial will take you through the steps required to write a contract test using Kotlin and Java.
The testing DSL allows one to define a piece of the ledger with transactions referring to each other, and ways of
verifying their correctness.
@@ -24,10 +24,13 @@ We start with the empty ledger:
.. sourcecode:: kotlin
- @Test
- fun emptyLedger() {
- ledger {
+ class CommercialPaperTest{
+ @Test
+ fun emptyLedger() {
+ ledger {
+ }
}
+ ...
}
.. sourcecode:: java
@@ -45,18 +48,43 @@ We start with the empty ledger:
The DSL keyword ``ledger`` takes a closure that can build up several transactions and may verify their overall
correctness. A ledger is effectively a fresh world with no pre-existing transactions or services within it.
-Let's add a Cash transaction:
+We will start with defining helper function that returns a ``CommercialPaper`` state:
+
+.. container:: codeset
+
+ .. sourcecode:: kotlin
+
+ fun getPaper(): ICommercialPaperState = CommercialPaper.State(
+ issuance = MEGA_CORP.ref(123),
+ owner = MEGA_CORP_PUBKEY,
+ faceValue = 1000.DOLLARS `issued by` MEGA_CORP.ref(123),
+ maturityDate = TEST_TX_TIME + 7.days
+ )
+
+ .. sourcecode:: java
+
+ private final OpaqueBytes defaultRef = new OpaqueBytes(new byte[]{123});
+
+ private ICommercialPaperState getPaper() {
+ return new JavaCommercialPaper.State(
+ getMEGA_CORP().ref(defaultRef),
+ getMEGA_CORP_PUBKEY(),
+ issuedBy(DOLLARS(1000), getMEGA_CORP().ref(defaultRef)),
+ getTEST_TX_TIME().plus(7, ChronoUnit.DAYS)
+ );
+ }
+
+It's a ``CommercialPaper`` issued by ``MEGA_CORP`` with face value of $1000 and maturity date in 7 days.
+
+Let's add a ``CommercialPaper`` transaction:
.. container:: codeset
.. sourcecode:: kotlin
@Test
- fun simpleCashDoesntCompile() {
- val inState = Cash.State(
- amount = 1000.DOLLARS `issued by` DUMMY_CASH_ISSUER,
- owner = DUMMY_PUBKEY_1
- )
+ fun simpleCPDoesntCompile() {
+ val inState = getPaper()
ledger {
transaction {
input(inState)
@@ -67,11 +95,8 @@ Let's add a Cash transaction:
.. sourcecode:: java
@Test
- public void simpleCashDoesntCompile() {
- Cash.State inState = new Cash.State(
- issuedBy(DOLLARS(1000), getDUMMY_CASH_ISSUER()),
- getDUMMY_PUBKEY_1()
- );
+ public void simpleCPDoesntCompile() {
+ ICommercialPaperState inState = getPaper();
ledger(l -> {
l.transaction(tx -> {
tx.input(inState);
@@ -83,7 +108,7 @@ Let's add a Cash transaction:
We can add a transaction to the ledger using the ``transaction`` primitive. The transaction in turn may be defined by
specifying ``input``-s, ``output``-s, ``command``-s and ``attachment``-s.
-The above ``input`` call is a bit special: Transactions don't actually contain input states, just references
+The above ``input`` call is a bit special; transactions don't actually contain input states, just references
to output states of other transactions. Under the hood the above ``input`` call creates a dummy transaction in the
ledger (that won't be verified) which outputs the specified state, and references that from this transaction.
@@ -93,11 +118,11 @@ The above code however doesn't compile:
.. sourcecode:: kotlin
- Error:(26, 21) Kotlin: Type mismatch: inferred type is Unit but EnforceVerifyOrFail was expected
+ Error:(29, 17) Kotlin: Type mismatch: inferred type is Unit but EnforceVerifyOrFail was expected
.. sourcecode:: java
- Error:(26, 31) java: incompatible types: bad return type in lambda expression missing return value
+ Error:(35, 27) java: incompatible types: bad return type in lambda expression missing return value
This is deliberate: The DSL forces us to specify either ``this.verifies()`` or ``this `fails with` "some text"`` on the
last line of ``transaction``:
@@ -107,11 +132,8 @@ last line of ``transaction``:
.. sourcecode:: kotlin
@Test
- fun simpleCash() {
- val inState = Cash.State(
- amount = 1000.DOLLARS `issued by` MEGA_CORP.ref(1, 1),
- owner = DUMMY_PUBKEY_1
- )
+ fun simpleCP() {
+ val inState = getPaper()
ledger {
transaction {
input(inState)
@@ -123,11 +145,8 @@ last line of ``transaction``:
.. sourcecode:: java
@Test
- public void simpleCash() {
- Cash.State inState = new Cash.State(
- issuedBy(DOLLARS(1000), getMEGA_CORP().ref((byte)1, (byte)1)),
- getDUMMY_PUBKEY_1()
- );
+ public void simpleCP() {
+ ICommercialPaperState inState = getPaper();
ledger(l -> {
l.transaction(tx -> {
tx.input(inState);
@@ -137,30 +156,20 @@ last line of ``transaction``:
});
}
-The code finally compiles. When run, it produces the following error::
-
- net.corda.core.contracts.TransactionVerificationException$ContractRejection: java.lang.IllegalArgumentException: Failed requirement: for deposit [01] at issuer Snake Oil Issuer the amounts balance
-
-.. note:: The reference here to the 'Snake Oil Issuer' is because we are using the pre-canned ``DUMMY_CASH_ISSUER``
- identity as the issuer of our cash.
-
-The transaction verification failed, because the sum of inputs does not equal the sum of outputs. We can specify that
-this is intended behaviour by changing ``this.verifies()`` to ``this `fails with` "the amounts balance"``:
+Let's take a look at a transaction that fails.
.. container:: codeset
.. sourcecode:: kotlin
@Test
- fun simpleCashFailsWith() {
- val inState = Cash.State(
- amount = 1000.DOLLARS `issued by` MEGA_CORP.ref(1, 1),
- owner = DUMMY_PUBKEY_1
- )
+ fun simpleCPMove() {
+ val inState = getPaper()
ledger {
transaction {
input(inState)
- this `fails with` "the amounts balance"
+ command(MEGA_CORP_PUBKEY) { CommercialPaper.Commands.Move() }
+ this.verifies()
}
}
}
@@ -168,15 +177,59 @@ this is intended behaviour by changing ``this.verifies()`` to ``this `fails with
.. sourcecode:: java
@Test
- public void simpleCashFailsWith() {
- Cash.State inState = new Cash.State(
- issuedBy(DOLLARS(1000), getMEGA_CORP().ref((byte)1, (byte)1)),
- getDUMMY_PUBKEY_1()
- );
+ public void simpleCPMove() {
+ ICommercialPaperState inState = getPaper();
ledger(l -> {
l.transaction(tx -> {
tx.input(inState);
- return tx.failsWith("the amounts balance");
+ tx.command(getMEGA_CORP_PUBKEY(), new JavaCommercialPaper.Commands.Move());
+ return tx.verifies();
+ });
+ return Unit.INSTANCE;
+ });
+ }
+
+When run, that code produces the following error:
+
+.. container:: codeset
+
+ .. sourcecode:: kotlin
+
+ net.corda.core.contracts.TransactionVerificationException$ContractRejection: java.lang.IllegalArgumentException: Failed requirement: the state is propagated
+
+ .. sourcecode:: java
+
+ net.corda.core.contracts.TransactionVerificationException$ContractRejection: java.lang.IllegalStateException: the state is propagated
+
+The transaction verification failed, because we wanted to move paper but didn't specify an output - but the state should be propagated.
+However we can specify that this is an intended behaviour by changing ``this.verifies()`` to ``this `fails with` "the state is propagated"``:
+
+.. container:: codeset
+
+ .. sourcecode:: kotlin
+
+ @Test
+ fun simpleCPMoveFails() {
+ val inState = getPaper()
+ ledger {
+ transaction {
+ input(inState)
+ command(MEGA_CORP_PUBKEY) { CommercialPaper.Commands.Move() }
+ this `fails with` "the state is propagated"
+ }
+ }
+ }
+
+ .. sourcecode:: java
+
+ @Test
+ public void simpleCPMoveFails() {
+ ICommercialPaperState inState = getPaper();
+ ledger(l -> {
+ l.transaction(tx -> {
+ tx.input(inState);
+ tx.command(getMEGA_CORP_PUBKEY(), new JavaCommercialPaper.Commands.Move());
+ return tx.failsWith("the state is propagated");
});
return Unit.INSTANCE;
});
@@ -189,17 +242,14 @@ We can continue to build the transaction until it ``verifies``:
.. sourcecode:: kotlin
@Test
- fun simpleCashSuccess() {
- val inState = Cash.State(
- amount = 1000.DOLLARS `issued by` MEGA_CORP.ref(1, 1),
- owner = DUMMY_PUBKEY_1
- )
+ fun simpleCPMoveSuccess() {
+ val inState = getPaper()
ledger {
transaction {
input(inState)
- this `fails with` "the amounts balance"
- output(inState.copy(owner = DUMMY_PUBKEY_2))
- command(DUMMY_PUBKEY_1) { Cash.Commands.Move() }
+ command(MEGA_CORP_PUBKEY) { CommercialPaper.Commands.Move() }
+ this `fails with` "the state is propagated"
+ output("alice's paper") { inState `owned by` ALICE_PUBKEY }
this.verifies()
}
}
@@ -208,55 +258,45 @@ We can continue to build the transaction until it ``verifies``:
.. sourcecode:: java
@Test
- public void simpleCashSuccess() {
- Cash.State inState = new Cash.State(
- issuedBy(DOLLARS(1000), getMEGA_CORP().ref((byte)1, (byte)1)),
- getDUMMY_PUBKEY_1()
- );
+ public void simpleCPMoveSuccess() {
+ ICommercialPaperState inState = getPaper();
ledger(l -> {
l.transaction(tx -> {
tx.input(inState);
- tx.failsWith("the amounts balance");
- tx.output(inState.copy(inState.getAmount(), getDUMMY_PUBKEY_2()));
- tx.command(getDUMMY_PUBKEY_1(), new Cash.Commands.Move());
+ tx.command(getMEGA_CORP_PUBKEY(), new JavaCommercialPaper.Commands.Move());
+ tx.failsWith("the state is propagated");
+ tx.output("alice's paper", inState.withOwner(getALICE_PUBKEY()));
return tx.verifies();
});
return Unit.INSTANCE;
});
}
-``output`` specifies that we want the input state to be transferred to ``DUMMY_PUBKEY_2`` and ``command`` adds the
-``Move`` command itself, signed by the current owner of the input state, ``DUMMY_PUBKEY_1``.
+``output`` specifies that we want the input state to be transferred to ``ALICE`` and ``command`` adds the
+``Move`` command itself, signed by the current owner of the input state, ``MEGA_CORP_PUBKEY``.
-We constructed a complete signed cash transaction from ``DUMMY_PUBKEY_1`` to ``DUMMY_PUBKEY_2`` and verified it. Note
-how we left in the ``fails with`` line - this is fine, the failure will be tested on the partially constructed
-transaction.
+We constructed a complete signed commercial paper transaction and verified it. Note how we left in the ``fails with``
+line - this is fine, the failure will be tested on the partially constructed transaction.
What should we do if we wanted to test what happens when the wrong party signs the transaction? If we simply add a
-``command`` it will ruin the transaction for good... Enter ``tweak``:
+``command`` it will permanently ruin the transaction... Enter ``tweak``:
.. container:: codeset
.. sourcecode:: kotlin
@Test
- fun simpleCashTweakSuccess() {
- val inState = Cash.State(
- amount = 1000.DOLLARS `issued by` MEGA_CORP.ref(1, 1),
- owner = DUMMY_PUBKEY_1
- )
+ fun `simple issuance with tweak`() {
ledger {
transaction {
- input(inState)
- this `fails with` "the amounts balance"
- output(inState.copy(owner = DUMMY_PUBKEY_2))
-
+ output("paper") { getPaper() } // Some CP is issued onto the ledger by MegaCorp.
tweak {
- command(DUMMY_PUBKEY_2) { Cash.Commands.Move() }
- this `fails with` "the owning keys are the same as the signing keys"
+ command(DUMMY_PUBKEY_1) { CommercialPaper.Commands.Issue() }
+ timestamp(TEST_TX_TIME)
+ this `fails with` "output states are issued by a command signer"
}
-
- command(DUMMY_PUBKEY_1) { Cash.Commands.Move() }
+ command(MEGA_CORP_PUBKEY) { CommercialPaper.Commands.Issue() }
+ timestamp(TEST_TX_TIME)
this.verifies()
}
}
@@ -265,33 +305,29 @@ What should we do if we wanted to test what happens when the wrong party signs t
.. sourcecode:: java
@Test
- public void simpleCashTweakSuccess() {
- Cash.State inState = new Cash.State(
- issuedBy(DOLLARS(1000), getMEGA_CORP().ref((byte)1, (byte)1)),
- getDUMMY_PUBKEY_1()
- );
+ public void simpleIssuanceWithTweak() {
ledger(l -> {
l.transaction(tx -> {
- tx.input(inState);
- tx.failsWith("the amounts balance");
- tx.output(inState.copy(inState.getAmount(), getDUMMY_PUBKEY_2()));
-
+ tx.output("paper", getPaper()); // Some CP is issued onto the ledger by MegaCorp.
tx.tweak(tw -> {
- tw.command(getDUMMY_PUBKEY_2(), new Cash.Commands.Move());
- return tw.failsWith("the owning keys are the same as the signing keys");
+ tw.command(getDUMMY_PUBKEY_1(), new JavaCommercialPaper.Commands.Issue());
+ tw.timestamp(getTEST_TX_TIME());
+ return tw.failsWith("output states are issued by a command signer");
});
- tx.command(getDUMMY_PUBKEY_1(), new Cash.Commands.Move());
+ tx.command(getMEGA_CORP_PUBKEY(), new JavaCommercialPaper.Commands.Issue());
+ tx.timestamp(getTEST_TX_TIME());
return tx.verifies();
});
return Unit.INSTANCE;
});
}
-``tweak`` creates a local copy of the transaction. This allows the local "ruining" of the transaction allowing testing
-of different error conditions.
+
+``tweak`` creates a local copy of the transaction. This makes possible to locally "ruin" the transaction while not
+modifying the original one, allowing testing of different error conditions.
We now have a neat little test that tests a single transaction. This is already useful, and in fact testing of a single
-transaction in this way is very common. There is even a shorthand toplevel ``transaction`` primitive that creates a
+transaction in this way is very common. There is even a shorthand top-level ``transaction`` primitive that creates a
ledger with a single transaction:
.. container:: codeset
@@ -299,22 +335,16 @@ ledger with a single transaction:
.. sourcecode:: kotlin
@Test
- fun simpleCashTweakSuccessTopLevelTransaction() {
- val inState = Cash.State(
- amount = 1000.DOLLARS `issued by` MEGA_CORP.ref(1, 1),
- owner = DUMMY_PUBKEY_1
- )
+ fun `simple issuance with tweak and top level transaction`() {
transaction {
- input(inState)
- this `fails with` "the amounts balance"
- output(inState.copy(owner = DUMMY_PUBKEY_2))
-
+ output("paper") { getPaper() } // Some CP is issued onto the ledger by MegaCorp.
tweak {
- command(DUMMY_PUBKEY_2) { Cash.Commands.Move() }
- this `fails with` "the owning keys are the same as the signing keys"
+ command(DUMMY_PUBKEY_1) { CommercialPaper.Commands.Issue() }
+ timestamp(TEST_TX_TIME)
+ this `fails with` "output states are issued by a command signer"
}
-
- command(DUMMY_PUBKEY_1) { Cash.Commands.Move() }
+ command(MEGA_CORP_PUBKEY) { CommercialPaper.Commands.Issue() }
+ timestamp(TEST_TX_TIME)
this.verifies()
}
}
@@ -322,21 +352,16 @@ ledger with a single transaction:
.. sourcecode:: java
@Test
- public void simpleCashTweakSuccessTopLevelTransaction() {
- Cash.State inState = new Cash.State(
- issuedBy(DOLLARS(1000), getMEGA_CORP().ref((byte)1, (byte)1)),
- getDUMMY_PUBKEY_1()
- );
+ public void simpleIssuanceWithTweakTopLevelTx() {
transaction(tx -> {
- tx.input(inState);
- tx.failsWith("the amounts balance");
- tx.output(inState.copy(inState.getAmount(), getDUMMY_PUBKEY_2()));
-
+ tx.output("paper", getPaper()); // Some CP is issued onto the ledger by MegaCorp.
tx.tweak(tw -> {
- tw.command(getDUMMY_PUBKEY_2(), new Cash.Commands.Move());
- return tw.failsWith("the owning keys are the same as the signing keys");
+ tw.command(getDUMMY_PUBKEY_1(), new JavaCommercialPaper.Commands.Issue());
+ tw.timestamp(getTEST_TX_TIME());
+ return tw.failsWith("output states are issued by a command signer");
});
- tx.command(getDUMMY_PUBKEY_1(), new Cash.Commands.Move());
+ tx.command(getMEGA_CORP_PUBKEY(), new JavaCommercialPaper.Commands.Issue());
+ tx.timestamp(getTEST_TX_TIME());
return tx.verifies();
});
}
@@ -351,21 +376,30 @@ Now that we know how to define a single transaction, let's look at how to define
.. sourcecode:: kotlin
@Test
- fun chainCash() {
+ fun `chain commercial paper`() {
+ val issuer = MEGA_CORP.ref(123)
+
ledger {
unverifiedTransaction {
- output("MEGA_CORP cash") {
- Cash.State(
- amount = 1000.DOLLARS `issued by` MEGA_CORP.ref(1, 1),
- owner = MEGA_CORP_PUBKEY
- )
- }
+ output("alice's $900", 900.DOLLARS.CASH `issued by` issuer `owned by` ALICE_PUBKEY)
}
- transaction {
- input("MEGA_CORP cash")
- output("MEGA_CORP cash".output().copy(owner = DUMMY_PUBKEY_1))
- command(MEGA_CORP_PUBKEY) { Cash.Commands.Move() }
+ // Some CP is issued onto the ledger by MegaCorp.
+ transaction("Issuance") {
+ output("paper") { getPaper() }
+ command(MEGA_CORP_PUBKEY) { CommercialPaper.Commands.Issue() }
+ timestamp(TEST_TX_TIME)
+ this.verifies()
+ }
+
+
+ transaction("Trade") {
+ input("paper")
+ input("alice's $900")
+ output("borrowed $900") { 900.DOLLARS.CASH `issued by` issuer `owned by` MEGA_CORP_PUBKEY }
+ output("alice's paper") { "paper".output() `owned by` ALICE_PUBKEY }
+ command(ALICE_PUBKEY) { Cash.Commands.Move() }
+ command(MEGA_CORP_PUBKEY) { CommercialPaper.Commands.Move() }
this.verifies()
}
}
@@ -374,141 +408,176 @@ Now that we know how to define a single transaction, let's look at how to define
.. sourcecode:: java
@Test
- public void chainCash() {
+ public void chainCommercialPaper() {
+ PartyAndReference issuer = getMEGA_CORP().ref(defaultRef);
ledger(l -> {
l.unverifiedTransaction(tx -> {
- tx.output("MEGA_CORP cash",
- new Cash.State(
- issuedBy(DOLLARS(1000), getMEGA_CORP().ref((byte)1, (byte)1)),
- getMEGA_CORP_PUBKEY()
- )
- );
- return Unit.INSTANCE;
- });
+ tx.output("alice's $900",
+ new Cash.State(issuedBy(DOLLARS(900), issuer), getALICE_PUBKEY(), null));
+ return Unit.INSTANCE;
+ });
- l.transaction(tx -> {
- tx.input("MEGA_CORP cash");
- Cash.State inputCash = l.retrieveOutput(Cash.State.class, "MEGA_CORP cash");
- tx.output(inputCash.copy(inputCash.getAmount(), getDUMMY_PUBKEY_1()));
- tx.command(getMEGA_CORP_PUBKEY(), new Cash.Commands.Move());
+ // Some CP is issued onto the ledger by MegaCorp.
+ l.transaction("Issuance", tx -> {
+ tx.output("paper", getPaper());
+ tx.command(getMEGA_CORP_PUBKEY(), new JavaCommercialPaper.Commands.Issue());
+ tx.timestamp(getTEST_TX_TIME());
return tx.verifies();
});
+ l.transaction("Trade", tx -> {
+ tx.input("paper");
+ tx.input("alice's $900");
+ tx.output("borrowed $900", new Cash.State(issuedBy(DOLLARS(900), issuer), getMEGA_CORP_PUBKEY(), null));
+ JavaCommercialPaper.State inputPaper = l.retrieveOutput(JavaCommercialPaper.State.class, "paper");
+ tx.output("alice's paper", inputPaper.withOwner(getALICE_PUBKEY()));
+ tx.command(getALICE_PUBKEY(), new Cash.Commands.Move());
+ tx.command(getMEGA_CORP_PUBKEY(), new JavaCommercialPaper.Commands.Move());
+ return tx.verifies();
+ });
return Unit.INSTANCE;
});
}
-In this example we declare that ``MEGA_CORP`` has a thousand dollars but we don't care where from, for this we can use
+
+In this example we declare that ``ALICE`` has $900 but we don't care where from. For this we can use
``unverifiedTransaction``. Note how we don't need to specify ``this.verifies()``.
-The ``output`` cash was labelled with ``"MEGA_CORP cash"``, we can subsequently referred to this other transactions, e.g.
-by ``input("MEGA_CORP cash")`` or ``"MEGA_CORP cash".output()``.
+Notice that we labelled output with ``"alice's $900"``, also in transaction named ``"Issuance"``
+we labelled a commercial paper with ``"paper"``. Now we can subsequently refer to them in other transactions, e.g.
+by ``input("alice's $900")`` or ``"paper".output()``.
-What happens if we reuse the output cash twice?
+The last transaction named ``"Trade"`` exemplifies simple fact of selling the ``CommercialPaper`` to Alice for her $900,
+$100 less than the face value at 10% interest after only 7 days.
+
+We can also test whole ledger calling ``this.verifies()`` and ``this.fails()`` on the ledger level.
+To do so let's create a simple example that uses the same input twice:
.. container:: codeset
.. sourcecode:: kotlin
@Test
- fun chainCashDoubleSpend() {
+ fun `chain commercial paper double spend`() {
+ val issuer = MEGA_CORP.ref(123)
ledger {
unverifiedTransaction {
- output("MEGA_CORP cash") {
- Cash.State(
- amount = 1000.DOLLARS `issued by` MEGA_CORP.ref(1, 1),
- owner = MEGA_CORP_PUBKEY
- )
- }
+ output("alice's $900", 900.DOLLARS.CASH `issued by` issuer `owned by` ALICE_PUBKEY)
}
- transaction {
- input("MEGA_CORP cash")
- output("MEGA_CORP cash".output().copy(owner = DUMMY_PUBKEY_1))
- command(MEGA_CORP_PUBKEY) { Cash.Commands.Move() }
+ // Some CP is issued onto the ledger by MegaCorp.
+ transaction("Issuance") {
+ output("paper") { getPaper() }
+ command(MEGA_CORP_PUBKEY) { CommercialPaper.Commands.Issue() }
+ timestamp(TEST_TX_TIME)
+ this.verifies()
+ }
+
+ transaction("Trade") {
+ input("paper")
+ input("alice's $900")
+ output("borrowed $900") { 900.DOLLARS.CASH `issued by` issuer `owned by` MEGA_CORP_PUBKEY }
+ output("alice's paper") { "paper".output() `owned by` ALICE_PUBKEY }
+ command(ALICE_PUBKEY) { Cash.Commands.Move() }
+ command(MEGA_CORP_PUBKEY) { CommercialPaper.Commands.Move() }
this.verifies()
}
transaction {
- input("MEGA_CORP cash")
- // We send it to another pubkey so that the transaction is not identical to the previous one
- output("MEGA_CORP cash".output().copy(owner = DUMMY_PUBKEY_2))
- command(MEGA_CORP_PUBKEY) { Cash.Commands.Move() }
+ input("paper")
+ // We moved a paper to another pubkey.
+ output("bob's paper") { "paper".output() `owned by` BOB_PUBKEY }
+ command(MEGA_CORP_PUBKEY) { CommercialPaper.Commands.Move() }
this.verifies()
}
+
+ this.fails()
}
}
.. sourcecode:: java
@Test
- public void chainCashDoubleSpend() {
+ public void chainCommercialPaperDoubleSpend() {
+ PartyAndReference issuer = getMEGA_CORP().ref(defaultRef);
ledger(l -> {
l.unverifiedTransaction(tx -> {
- tx.output("MEGA_CORP cash",
- new Cash.State(
- issuedBy(DOLLARS(1000), getMEGA_CORP().ref((byte)1, (byte)1)),
- getMEGA_CORP_PUBKEY()
- )
- );
+ tx.output("alice's $900",
+ new Cash.State(issuedBy(DOLLARS(900), issuer), getALICE_PUBKEY(), null));
return Unit.INSTANCE;
});
- l.transaction(tx -> {
- tx.input("MEGA_CORP cash");
- Cash.State inputCash = l.retrieveOutput(Cash.State.class, "MEGA_CORP cash");
- tx.output(inputCash.copy(inputCash.getAmount(), getDUMMY_PUBKEY_1()));
- tx.command(getMEGA_CORP_PUBKEY(), new Cash.Commands.Move());
+ // Some CP is issued onto the ledger by MegaCorp.
+ l.transaction("Issuance", tx -> {
+ tx.output("paper", getPaper());
+ tx.command(getMEGA_CORP_PUBKEY(), new JavaCommercialPaper.Commands.Issue());
+ tx.timestamp(getTEST_TX_TIME());
+ return tx.verifies();
+ });
+
+ l.transaction("Trade", tx -> {
+ tx.input("paper");
+ tx.input("alice's $900");
+ tx.output("borrowed $900", new Cash.State(issuedBy(DOLLARS(900), issuer), getMEGA_CORP_PUBKEY(), null));
+ JavaCommercialPaper.State inputPaper = l.retrieveOutput(JavaCommercialPaper.State.class, "paper");
+ tx.output("alice's paper", inputPaper.withOwner(getALICE_PUBKEY()));
+ tx.command(getALICE_PUBKEY(), new Cash.Commands.Move());
+ tx.command(getMEGA_CORP_PUBKEY(), new JavaCommercialPaper.Commands.Move());
return tx.verifies();
});
l.transaction(tx -> {
- tx.input("MEGA_CORP cash");
- Cash.State inputCash = l.retrieveOutput(Cash.State.class, "MEGA_CORP cash");
- // We send it to another pubkey so that the transaction is not identical to the previous one
- tx.output(inputCash.copy(inputCash.getAmount(), getDUMMY_PUBKEY_2()));
- tx.command(getMEGA_CORP_PUBKEY(), new Cash.Commands.Move());
+ tx.input("paper");
+ JavaCommercialPaper.State inputPaper = l.retrieveOutput(JavaCommercialPaper.State.class, "paper");
+ // We moved a paper to other pubkey.
+ tx.output("bob's paper", inputPaper.withOwner(getBOB_PUBKEY()));
+ tx.command(getMEGA_CORP_PUBKEY(), new JavaCommercialPaper.Commands.Move());
return tx.verifies();
});
-
+ l.fails();
return Unit.INSTANCE;
});
}
-The transactions ``verifies()`` individually, however the state was spent twice!
-
-We can also verify the complete ledger by calling ``verifies``/``fails`` on the ledger level. We can also use
-``tweak`` to create a local copy of the whole ledger:
+The transactions ``verifies()`` individually, however the state was spent twice! That's why we need the global ledger
+verification (``this.fails()`` at the end). As in previous examples we can use ``tweak`` to create a local copy of the whole ledger:
.. container:: codeset
.. sourcecode:: kotlin
@Test
- fun chainCashDoubleSpendFailsWith() {
+ fun `chain commercial tweak`() {
+ val issuer = MEGA_CORP.ref(123)
ledger {
unverifiedTransaction {
- output("MEGA_CORP cash") {
- Cash.State(
- amount = 1000.DOLLARS `issued by` MEGA_CORP.ref(1, 1),
- owner = MEGA_CORP_PUBKEY
- )
- }
+ output("alice's $900", 900.DOLLARS.CASH `issued by` issuer `owned by` ALICE_PUBKEY)
}
- transaction {
- input("MEGA_CORP cash")
- output("MEGA_CORP cash".output().copy(owner = DUMMY_PUBKEY_1))
- command(MEGA_CORP_PUBKEY) { Cash.Commands.Move() }
+ // Some CP is issued onto the ledger by MegaCorp.
+ transaction("Issuance") {
+ output("paper") { getPaper() }
+ command(MEGA_CORP_PUBKEY) { CommercialPaper.Commands.Issue() }
+ timestamp(TEST_TX_TIME)
+ this.verifies()
+ }
+
+ transaction("Trade") {
+ input("paper")
+ input("alice's $900")
+ output("borrowed $900") { 900.DOLLARS.CASH `issued by` issuer `owned by` MEGA_CORP_PUBKEY }
+ output("alice's paper") { "paper".output() `owned by` ALICE_PUBKEY }
+ command(ALICE_PUBKEY) { Cash.Commands.Move() }
+ command(MEGA_CORP_PUBKEY) { CommercialPaper.Commands.Move() }
this.verifies()
}
tweak {
transaction {
- input("MEGA_CORP cash")
- // We send it to another pubkey so that the transaction is not identical to the previous one
- output("MEGA_CORP cash".output().copy(owner = DUMMY_PUBKEY_1))
- command(MEGA_CORP_PUBKEY) { Cash.Commands.Move() }
+ input("paper")
+ // We moved a paper to another pubkey.
+ output("bob's paper") { "paper".output() `owned by` BOB_PUBKEY }
+ command(MEGA_CORP_PUBKEY) { CommercialPaper.Commands.Move() }
this.verifies()
}
this.fails()
@@ -521,39 +590,46 @@ We can also verify the complete ledger by calling ``verifies``/``fails`` on the
.. sourcecode:: java
@Test
- public void chainCashDoubleSpendFailsWith() {
+ public void chainCommercialPaperTweak() {
+ PartyAndReference issuer = getMEGA_CORP().ref(defaultRef);
ledger(l -> {
l.unverifiedTransaction(tx -> {
- tx.output("MEGA_CORP cash",
- new Cash.State(
- issuedBy(DOLLARS(1000), getMEGA_CORP().ref((byte)1, (byte)1)),
- getMEGA_CORP_PUBKEY()
- )
- );
+ tx.output("alice's $900",
+ new Cash.State(issuedBy(DOLLARS(900), issuer), getALICE_PUBKEY(), null));
return Unit.INSTANCE;
});
- l.transaction(tx -> {
- tx.input("MEGA_CORP cash");
- Cash.State inputCash = l.retrieveOutput(Cash.State.class, "MEGA_CORP cash");
- tx.output(inputCash.copy(inputCash.getAmount(), getDUMMY_PUBKEY_1()));
- tx.command(getMEGA_CORP_PUBKEY(), new Cash.Commands.Move());
+ // Some CP is issued onto the ledger by MegaCorp.
+ l.transaction("Issuance", tx -> {
+ tx.output("paper", getPaper());
+ tx.command(getMEGA_CORP_PUBKEY(), new JavaCommercialPaper.Commands.Issue());
+ tx.timestamp(getTEST_TX_TIME());
+ return tx.verifies();
+ });
+
+ l.transaction("Trade", tx -> {
+ tx.input("paper");
+ tx.input("alice's $900");
+ tx.output("borrowed $900", new Cash.State(issuedBy(DOLLARS(900), issuer), getMEGA_CORP_PUBKEY(), null));
+ JavaCommercialPaper.State inputPaper = l.retrieveOutput(JavaCommercialPaper.State.class, "paper");
+ tx.output("alice's paper", inputPaper.withOwner(getALICE_PUBKEY()));
+ tx.command(getALICE_PUBKEY(), new Cash.Commands.Move());
+ tx.command(getMEGA_CORP_PUBKEY(), new JavaCommercialPaper.Commands.Move());
return tx.verifies();
});
l.tweak(lw -> {
lw.transaction(tx -> {
- tx.input("MEGA_CORP cash");
- Cash.State inputCash = l.retrieveOutput(Cash.State.class, "MEGA_CORP cash");
- // We send it to another pubkey so that the transaction is not identical to the previous one
- tx.output(inputCash.copy(inputCash.getAmount(), getDUMMY_PUBKEY_2()));
- tx.command(getMEGA_CORP_PUBKEY(), new Cash.Commands.Move());
+ tx.input("paper");
+ JavaCommercialPaper.State inputPaper = l.retrieveOutput(JavaCommercialPaper.State.class, "paper");
+ // We moved a paper to another pubkey.
+ tx.output("bob's paper", inputPaper.withOwner(getBOB_PUBKEY()));
+ tx.command(getMEGA_CORP_PUBKEY(), new JavaCommercialPaper.Commands.Move());
return tx.verifies();
});
lw.fails();
return Unit.INSTANCE;
});
-
l.verifies();
return Unit.INSTANCE;
});
diff --git a/docs/build/html/api/alltypes/index.html b/docs/build/html/api/alltypes/index.html
index 0d9b465716..1532dd1c0e 100644
--- a/docs/build/html/api/alltypes/index.html
+++ b/docs/build/html/api/alltypes/index.html
@@ -1394,6 +1394,14 @@ quantifiable with integer quantities.
+net.corda.flows.IssuerFlow |
+
+ This flow enables a client to request issuance of some FungibleAsset from a
+server acting as an issuer (see Issued) of FungibleAssets.
+ |
+
+
+
kotlin.collections.Iterable (extensions in package net.corda.core.contracts) |
|
diff --git a/docs/build/html/api/index-outline.html b/docs/build/html/api/index-outline.html
index 5212f9da2c..d15a1e5a2a 100644
--- a/docs/build/html/api/index-outline.html
+++ b/docs/build/html/api/index-outline.html
@@ -619,7 +619,7 @@
ArtemisMessagingComponent()
-protected interface ArtemisAddress : MessageRecipients
+interface ArtemisAddress : MessageRecipients
-protected interface ArtemisPeerAddress : ArtemisAddress, SingleMessageRecipient
+interface ArtemisPeerAddress : ArtemisAddress, SingleMessageRecipient
const val INTERNAL_PREFIX: String
-val NETWORK_MAP_ADDRESS: <ERROR CLASS>
+val NETWORK_MAP_ADDRESS: String
const val NODE_USER: String
const val NOTIFICATIONS_ADDRESS: String
data class NetworkMapAddress : SingleMessageRecipient, ArtemisPeerAddress
@@ -695,6 +695,7 @@
const val P2P_QUEUE: String
const val PEERS_PREFIX: String
const val PEER_USER: String
+const val RPC_QUEUE_REMOVALS_QUEUE: String
const val RPC_REQUESTS_QUEUE: String
const val SERVICES_PREFIX: String
data class ServiceAddress : ArtemisAddress, MessageRecipientGroup
@@ -748,8 +749,8 @@
-fun bridgeToNetworkMapService(networkMapService: NetworkMapAddress): Unit
val config: NodeConfiguration
+fun deployBridgeIfAbsent(queueName: <ERROR CLASS>, hostAndPort: <ERROR CLASS>): Unit
val myHostPort: <ERROR CLASS>
val networkMapCache: NetworkMapCache
fun start(): Unit
@@ -1189,8 +1190,14 @@
CashFlow(command: CashCommand)
+CashFlow(command: CashCommand, progressTracker: ProgressTracker)
+object EXITING : Step
+object ISSUING : Step
+object PAYING : Step
fun call(): CashFlowResult
val command: CashCommand
+val progressTracker: ProgressTracker
+fun tracker(): ProgressTracker