Regens docs.

This commit is contained in:
Joel Dudley
2017-01-06 17:38:23 +00:00
parent 60f72d4427
commit a8a371fcda
3783 changed files with 13414 additions and 13063 deletions

View File

@ -98,7 +98,7 @@
<ul>
<li class="toctree-l1"><a class="reference internal" href="inthebox.html">What&#8217;s included?</a></li>
<li class="toctree-l1"><a class="reference internal" href="getting-set-up.html">Getting set up</a></li>
<li class="toctree-l1"><a class="reference internal" href="getting-set-up-fault-finding.html">Getting set up: troubleshooting</a></li>
<li class="toctree-l1"><a class="reference internal" href="getting-set-up-fault-finding.html">Troubleshooting</a></li>
<li class="toctree-l1"><a class="reference internal" href="running-the-demos.html">Running the demos</a></li>
<li class="toctree-l1"><a class="reference internal" href="CLI-vs-IDE.html">CLI vs IDE</a></li>
</ul>
@ -108,17 +108,12 @@
<li class="toctree-l1"><a class="reference internal" href="transaction-data-types.html">Data types</a></li>
<li class="toctree-l1"><a class="reference internal" href="merkle-trees.html">Transaction tear-offs</a></li>
<li class="toctree-l1"><a class="reference internal" href="consensus.html">Consensus model</a></li>
<li class="toctree-l1"><a class="reference internal" href="clauses.html">Clauses key concepts</a></li>
<li class="toctree-l1"><a class="reference internal" href="clauses.html">Clauses</a></li>
</ul>
<p class="caption"><span class="caption-text">CorDapps</span></p>
<ul>
<li class="toctree-l1"><a class="reference internal" href="creating-a-cordapp.html">CorDapps Background</a></li>
<li class="toctree-l1"><a class="reference internal" href="creating-a-cordapp.html#gradle-plugins-for-cordapps">Gradle plugins for CorDapps</a></li>
<li class="toctree-l1"><a class="reference internal" href="tutorial-cordapp.html">The CorDapp Template</a></li>
<li class="toctree-l1"><a class="reference internal" href="tutorial-cordapp.html#building-the-cordapp-template">Building the CorDapp template</a></li>
<li class="toctree-l1"><a class="reference internal" href="tutorial-cordapp.html#running-the-cordapp-template">Running the CorDapp template</a></li>
<li class="toctree-l1"><a class="reference internal" href="tutorial-cordapp.html#interacting-with-the-cordapp-template">Interacting with the CorDapp template</a></li>
<li class="toctree-l1"><a class="reference internal" href="tutorial-cordapp.html#extending-the-cordapp-template">Extending the CorDapp template</a></li>
<li class="toctree-l1"><a class="reference internal" href="creating-a-cordapp.html">CorDapp basics</a></li>
<li class="toctree-l1"><a class="reference internal" href="tutorial-cordapp.html">The CorDapp template</a></li>
</ul>
<p class="caption"><span class="caption-text">The Corda node</span></p>
<ul>
@ -137,16 +132,14 @@
<li class="toctree-l1"><a class="reference internal" href="tutorial-contract.html">Writing a contract</a></li>
<li class="toctree-l1"><a class="reference internal" href="tutorial-contract-clauses.html">Writing a contract using clauses</a></li>
<li class="toctree-l1"><a class="reference internal" href="tutorial-test-dsl.html">Writing a contract test</a></li>
<li class="toctree-l1"><a class="reference internal" href="tutorial-integration-testing.html">Integration Test Tutorial</a></li>
<li class="toctree-l1"><a class="reference internal" href="tutorial-integration-testing.html">Integration testing</a></li>
<li class="toctree-l1"><a class="reference internal" href="tutorial-clientrpc-api.html">Client RPC API tutorial</a></li>
<li class="toctree-l1"><a class="reference internal" href="tutorial-building-transactions.html">Building Transactions</a></li>
<li class="toctree-l1"><a class="reference internal" href="tutorial-building-transactions.html">Building transactions</a></li>
<li class="toctree-l1"><a class="reference internal" href="flow-state-machines.html">Writing flows</a></li>
<li class="toctree-l1"><a class="reference internal" href="flow-testing.html">Writing flow tests</a></li>
<li class="toctree-l1"><a class="reference internal" href="running-a-notary.html">Running a notary service</a></li>
<li class="toctree-l1"><a class="reference internal" href="using-a-notary.html">Using a notary service</a></li>
<li class="toctree-l1"><a class="reference internal" href="oracles.html">Writing oracle services</a></li>
<li class="toctree-l1"><a class="reference internal" href="oracles.html#implementing-an-oracle-with-continuously-varying-data">Implementing an oracle with continuously varying data</a></li>
<li class="toctree-l1"><a class="reference internal" href="oracles.html#using-an-oracle">Using an oracle</a></li>
<li class="toctree-l1 current"><a class="current reference internal" href="#">Using attachments</a><ul>
<li class="toctree-l2"><a class="reference internal" href="#attachments-demo">Attachments demo</a></li>
</ul>
@ -156,7 +149,6 @@
<p class="caption"><span class="caption-text">Other</span></p>
<ul>
<li class="toctree-l1"><a class="reference internal" href="network-simulator.html">Network Simulator</a></li>
<li class="toctree-l1"><a class="reference internal" href="initial-margin-agreement.html">Initial margin agreements</a></li>
</ul>
<p class="caption"><span class="caption-text">Component library</span></p>
<ul>
@ -166,11 +158,9 @@
<p class="caption"><span class="caption-text">Appendix</span></p>
<ul>
<li class="toctree-l1"><a class="reference internal" href="loadtesting.html">Load testing</a></li>
<li class="toctree-l1"><a class="reference internal" href="setting-up-a-corda-network.html">Introduction - What is a corda network?</a></li>
<li class="toctree-l1"><a class="reference internal" href="setting-up-a-corda-network.html#setting-up-your-own-network">Setting up your own network</a></li>
<li class="toctree-l1"><a class="reference internal" href="setting-up-a-corda-network.html">What is a corda network?</a></li>
<li class="toctree-l1"><a class="reference internal" href="secure-coding-guidelines.html">Secure coding guidelines</a></li>
<li class="toctree-l1"><a class="reference internal" href="release-process.html">Release process</a></li>
<li class="toctree-l1"><a class="reference internal" href="release-process.html#steps-to-cut-a-release">Steps to cut a release</a></li>
<li class="toctree-l1"><a class="reference internal" href="release-notes.html">Release notes</a></li>
<li class="toctree-l1"><a class="reference internal" href="codestyle.html">Code style guide</a></li>
<li class="toctree-l1"><a class="reference internal" href="building-the-docs.html">Building the documentation</a></li>
@ -234,10 +224,9 @@ nodes already. Examples include:</p>
<li>Metadata about a transaction, such as PDF version of an invoice being settled</li>
<li>Shared information to be permanently recorded on the ledger</li>
</ul>
<p>To add attachments the file must first be added to the node&#8217;s storage service using <code class="docutils literal"><span class="pre">StorageService.importAttachment()</span></code>,
which returns a unique ID that can be added using <code class="docutils literal"><span class="pre">TransactionBuilder.addAttachment()</span></code>. Attachments can also be
uploaded and downloaded via HTTP, to enable integration with external systems. For instructions on HTTP upload/download
please see &#8220;<a class="reference internal" href="node-administration.html"><span class="doc">Node administration</span></a>&#8221;.</p>
<p>To add attachments the file must first be added to uploaded to the node, which returns a unique ID that can be added
using <code class="docutils literal"><span class="pre">TransactionBuilder.addAttachment()</span></code>. Attachments can be uploaded and downloaded via RPC and HTTP. For
instructions on HTTP upload/download please see &#8220;<a class="reference internal" href="node-administration.html"><span class="doc">Node administration</span></a>&#8221;.</p>
<p>Normally attachments on transactions are fetched automatically via the <code class="docutils literal"><span class="pre">ResolveTransactionsFlow</span></code> when verifying
received transactions. Attachments are needed in order to validate a transaction (they include, for example, the
contract code), so must be fetched before the validation process can run. <code class="docutils literal"><span class="pre">ResolveTransactionsFlow</span></code> calls
@ -248,43 +237,42 @@ contract code), so must be fetched before the validation process can run. <code
<p>There is a worked example of attachments, which relays a simple document from one node to another. The &#8220;two party
trade flow&#8221; also includes an attachment, however it is a significantly more complex demo, and less well suited
for a tutorial.</p>
<p>The demo code is in the file &#8220;src/main/kotlin/net.corda.demos/attachment/AttachmentDemo.kt&#8221;, with the core logic
contained within the two functions <code class="docutils literal"><span class="pre">runRecipient()</span></code> and <code class="docutils literal"><span class="pre">runSender()</span></code>. We&#8217;ll look at the recipient function first;
this subscribes to notifications of new validated transactions, and if it receives a transaction containing attachments,
loads the first attachment from storage, and checks it matches the expected attachment ID. <code class="docutils literal"><span class="pre">ResolveTransactionsFlow</span></code>
has already fetched all attachments from the remote node, and as such the attachments are available from the node&#8217;s
storage service. Once the attachment is verified, the node shuts itself down.</p>
<div class="highlight-kotlin"><div class="highlight"><pre><span></span><span class="k">private</span> <span class="k">fun</span> <span class="nf">runRecipient</span><span class="p">(</span><span class="n">node</span><span class="p">:</span> <span class="n">Node</span><span class="p">)</span> <span class="p">{</span>
<span class="k">val</span> <span class="py">serviceHub</span> <span class="p">=</span> <span class="n">node</span><span class="p">.</span><span class="n">services</span>
<span class="c1">// Normally we would receive the transaction from a more specific flow, but in this case we let [FinalityFlow]</span>
<span class="c1">// handle receiving it for us.</span>
<span class="n">serviceHub</span><span class="p">.</span><span class="n">storageService</span><span class="p">.</span><span class="n">validatedTransactions</span><span class="p">.</span><span class="n">updates</span><span class="p">.</span><span class="n">subscribe</span> <span class="p">{</span> <span class="n">event</span> <span class="p">-&gt;</span>
<span class="c1">// When the transaction is received, it&#39;s passed through [ResolveTransactionsFlow], which first fetches any</span>
<span class="c1">// attachments for us, then verifies the transaction. As such, by the time it hits the validated transaction store,</span>
<span class="c1">// we have a copy of the attachment.</span>
<span class="k">val</span> <span class="py">tx</span> <span class="p">=</span> <span class="n">event</span><span class="p">.</span><span class="n">tx</span>
<span class="k">if</span> <span class="p">(</span><span class="n">tx</span><span class="p">.</span><span class="n">attachments</span><span class="p">.</span><span class="n">isNotEmpty</span><span class="p">())</span> <span class="p">{</span>
<span class="k">val</span> <span class="py">attachment</span> <span class="p">=</span> <span class="n">serviceHub</span><span class="p">.</span><span class="n">storageService</span><span class="p">.</span><span class="n">attachments</span><span class="p">.</span><span class="n">openAttachment</span><span class="p">(</span><span class="n">tx</span><span class="p">.</span><span class="n">attachments</span><span class="p">.</span><span class="n">first</span><span class="p">())</span>
<span class="n">assertEquals</span><span class="p">(</span><span class="n">PROSPECTUS_HASH</span><span class="p">,</span> <span class="n">attachment</span><span class="o">?.</span><span class="n">id</span><span class="p">)</span>
<span class="n">println</span><span class="p">(</span><span class="s">&quot;File received - we&#39;re happy!\n\nFinal transaction is:\n\n${Emoji.renderIfSupported(event.tx)}&quot;</span><span class="p">)</span>
<span class="n">thread</span> <span class="p">{</span>
<span class="n">node</span><span class="p">.</span><span class="n">stop</span><span class="p">()</span>
<span class="p">}</span>
<span class="p">}</span>
<p>The demo code is in the file <code class="docutils literal"><span class="pre">samples/attachment-demo/src/main/kotlin/net/corda/attachmentdemo/AttachmentDemo.kt</span></code>,
with the core logic contained within the two functions <code class="docutils literal"><span class="pre">recipient()</span></code> and <code class="docutils literal"><span class="pre">sender()</span></code>. The first thing it does is set
up an RPC connection to node B using a demo user account (this is all configured in the gradle build script for the demo
and the nodes will be created using the <code class="docutils literal"><span class="pre">deployNodes</span></code> gradle task as normal). The <code class="docutils literal"><span class="pre">CordaRPCClient.use</span></code> method is a
convenience helper intended for small tools that sets up an RPC connection scoped to the provided block, and brings all
the RPCs into scope. Once connected the sender/recipient functions are run with the RPC proxy as a parameter.</p>
<p>We&#8217;ll look at the recipient function first.</p>
<p>The first thing it does is wait to receive a notification of a new transaction by calling the <code class="docutils literal"><span class="pre">verifiedTransactions</span></code>
RPC, which returns both a snapshot and an observable of changes. The observable is made blocking and the next
transaction the node verifies is retrieved. That transaction is checked to see if it has the expected attachment
and if so, printed out.</p>
<div class="highlight-kotlin"><div class="highlight"><pre><span></span><span class="k">fun</span> <span class="nf">recipient</span><span class="p">(</span><span class="n">rpc</span><span class="p">:</span> <span class="n">CordaRPCOps</span><span class="p">)</span> <span class="p">{</span>
<span class="n">println</span><span class="p">(</span><span class="s">&quot;Waiting to receive transaction ...&quot;</span><span class="p">)</span>
<span class="k">val</span> <span class="py">stx</span> <span class="p">=</span> <span class="n">rpc</span><span class="p">.</span><span class="n">verifiedTransactions</span><span class="p">().</span><span class="n">second</span><span class="p">.</span><span class="n">toBlocking</span><span class="p">().</span><span class="n">first</span><span class="p">()</span>
<span class="k">val</span> <span class="py">wtx</span> <span class="p">=</span> <span class="n">stx</span><span class="p">.</span><span class="n">tx</span>
<span class="k">if</span> <span class="p">(</span><span class="n">wtx</span><span class="p">.</span><span class="n">attachments</span><span class="p">.</span><span class="n">isNotEmpty</span><span class="p">())</span> <span class="p">{</span>
<span class="n">assertEquals</span><span class="p">(</span><span class="n">PROSPECTUS_HASH</span><span class="p">,</span> <span class="n">wtx</span><span class="p">.</span><span class="n">attachments</span><span class="p">.</span><span class="n">first</span><span class="p">())</span>
<span class="n">require</span><span class="p">(</span><span class="n">rpc</span><span class="p">.</span><span class="n">attachmentExists</span><span class="p">(</span><span class="n">PROSPECTUS_HASH</span><span class="p">))</span>
<span class="n">println</span><span class="p">(</span><span class="s">&quot;File received - we&#39;re happy!\n\nFinal transaction is:\n\n${Emoji.renderIfSupported(wtx)}&quot;</span><span class="p">)</span>
<span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
<span class="n">println</span><span class="p">(</span><span class="s">&quot;Error: no attachments found in ${wtx.id}&quot;</span><span class="p">)</span>
<span class="p">}</span>
<span class="p">}</span>
</pre></div>
</div>
<p>The sender correspondingly builds a transaction with the attachment, then calls <code class="docutils literal"><span class="pre">FinalityFlow</span></code> to complete the
transaction and send it to the recipient node:</p>
<div class="highlight-kotlin"><div class="highlight"><pre><span></span><span class="k">private</span> <span class="k">fun</span> <span class="nf">runSender</span><span class="p">(</span><span class="n">node</span><span class="p">:</span> <span class="n">Node</span><span class="p">,</span> <span class="n">otherSide</span><span class="p">:</span> <span class="n">Party</span><span class="p">)</span> <span class="p">{</span>
<span class="k">val</span> <span class="py">serviceHub</span> <span class="p">=</span> <span class="n">node</span><span class="p">.</span><span class="n">services</span>
<div class="highlight-kotlin"><div class="highlight"><pre><span></span><span class="k">fun</span> <span class="nf">sender</span><span class="p">(</span><span class="n">rpc</span><span class="p">:</span> <span class="n">CordaRPCOps</span><span class="p">)</span> <span class="p">{</span>
<span class="c1">// Get the identity key of the other side (the recipient).</span>
<span class="k">val</span> <span class="py">otherSide</span><span class="p">:</span> <span class="n">Party</span> <span class="p">=</span> <span class="n">rpc</span><span class="p">.</span><span class="n">partyFromName</span><span class="p">(</span><span class="s">&quot;Bank B&quot;</span><span class="p">)</span><span class="o">!!</span>
<span class="c1">// Make sure we have the file in storage</span>
<span class="k">if</span> <span class="p">(</span><span class="n">serviceHub</span><span class="p">.</span><span class="n">storageService</span><span class="p">.</span><span class="n">attachments</span><span class="p">.</span><span class="n">openAttachment</span><span class="p">(</span><span class="n">PROSPECTUS_HASH</span><span class="p">)</span> <span class="p">==</span> <span class="k">null</span><span class="p">)</span> <span class="p">{</span>
<span class="n">net</span><span class="p">.</span><span class="n">corda</span><span class="p">.</span><span class="n">demos</span><span class="p">.</span><span class="n">Role</span><span class="o">::</span><span class="k">class</span><span class="p">.</span><span class="n">java</span><span class="p">.</span><span class="n">getResourceAsStream</span><span class="p">(</span><span class="s">&quot;bank-of-london-cp.jar&quot;</span><span class="p">).</span><span class="n">use</span> <span class="p">{</span>
<span class="k">val</span> <span class="py">id</span> <span class="p">=</span> <span class="n">node</span><span class="p">.</span><span class="n">storage</span><span class="p">.</span><span class="n">attachments</span><span class="p">.</span><span class="n">importAttachment</span><span class="p">(</span><span class="n">it</span><span class="p">)</span>
<span class="c1">// TODO: We should have our own demo file, not share the trader demo file</span>
<span class="k">if</span> <span class="p">(!</span><span class="n">rpc</span><span class="p">.</span><span class="n">attachmentExists</span><span class="p">(</span><span class="n">PROSPECTUS_HASH</span><span class="p">))</span> <span class="p">{</span>
<span class="n">Thread</span><span class="p">.</span><span class="n">currentThread</span><span class="p">().</span><span class="n">contextClassLoader</span><span class="p">.</span><span class="n">getResourceAsStream</span><span class="p">(</span><span class="s">&quot;bank-of-london-cp.jar&quot;</span><span class="p">).</span><span class="n">use</span> <span class="p">{</span>
<span class="k">val</span> <span class="py">id</span> <span class="p">=</span> <span class="n">rpc</span><span class="p">.</span><span class="n">uploadAttachment</span><span class="p">(</span><span class="n">it</span><span class="p">)</span>
<span class="n">assertEquals</span><span class="p">(</span><span class="n">PROSPECTUS_HASH</span><span class="p">,</span> <span class="n">id</span><span class="p">)</span>
<span class="p">}</span>
<span class="p">}</span>
@ -292,24 +280,27 @@ transaction and send it to the recipient node:</p>
<span class="c1">// Create a trivial transaction that just passes across the attachment - in normal cases there would be</span>
<span class="c1">// inputs, outputs and commands that refer to this attachment.</span>
<span class="k">val</span> <span class="py">ptx</span> <span class="p">=</span> <span class="n">TransactionType</span><span class="p">.</span><span class="n">General</span><span class="p">.</span><span class="n">Builder</span><span class="p">(</span><span class="n">notary</span> <span class="p">=</span> <span class="k">null</span><span class="p">)</span>
<span class="n">ptx</span><span class="p">.</span><span class="n">addAttachment</span><span class="p">(</span><span class="n">serviceHub</span><span class="p">.</span><span class="n">storageService</span><span class="p">.</span><span class="n">attachments</span><span class="p">.</span><span class="n">openAttachment</span><span class="p">(</span><span class="n">PROSPECTUS_HASH</span><span class="p">)</span><span class="o">!!</span><span class="p">.</span><span class="n">id</span><span class="p">)</span>
<span class="n">require</span><span class="p">(</span><span class="n">rpc</span><span class="p">.</span><span class="n">attachmentExists</span><span class="p">(</span><span class="n">PROSPECTUS_HASH</span><span class="p">))</span>
<span class="n">ptx</span><span class="p">.</span><span class="n">addAttachment</span><span class="p">(</span><span class="n">PROSPECTUS_HASH</span><span class="p">)</span>
<span class="c1">// TODO: Add a dummy state and specify a notary, so that the tx hash is randomised each time and the demo can be repeated.</span>
<span class="c1">// Despite not having any states, we have to have at least one signature on the transaction</span>
<span class="n">ptx</span><span class="p">.</span><span class="n">signWith</span><span class="p">(</span><span class="n">ALICE_KEY</span><span class="p">)</span>
<span class="c1">// Send the transaction to the other recipient</span>
<span class="k">val</span> <span class="py">tx</span> <span class="p">=</span> <span class="n">ptx</span><span class="p">.</span><span class="n">toSignedTransaction</span><span class="p">()</span>
<span class="n">serviceHub</span><span class="p">.</span><span class="n">startFlow</span><span class="p">(</span><span class="n">LOG_SENDER</span><span class="p">,</span> <span class="n">FinalityFlow</span><span class="p">(</span><span class="n">tx</span><span class="p">,</span> <span class="n">emptySet</span><span class="p">(),</span> <span class="n">setOf</span><span class="p">(</span><span class="n">otherSide</span><span class="p">))).</span><span class="n">success</span> <span class="p">{</span>
<span class="n">thread</span> <span class="p">{</span>
<span class="n">Thread</span><span class="p">.</span><span class="n">sleep</span><span class="p">(</span><span class="m">1000L</span><span class="p">)</span> <span class="c1">// Give the other side time to request the attachment</span>
<span class="n">node</span><span class="p">.</span><span class="n">stop</span><span class="p">()</span>
<span class="p">}</span>
<span class="p">}.</span><span class="n">failure</span> <span class="p">{</span>
<span class="n">println</span><span class="p">(</span><span class="s">&quot;Failed to relay message &quot;</span><span class="p">)</span>
<span class="p">}</span>
<span class="k">val</span> <span class="py">stx</span> <span class="p">=</span> <span class="n">ptx</span><span class="p">.</span><span class="n">toSignedTransaction</span><span class="p">()</span>
<span class="n">println</span><span class="p">(</span><span class="s">&quot;Sending ${stx.id}&quot;</span><span class="p">)</span>
<span class="k">val</span> <span class="py">protocolHandle</span> <span class="p">=</span> <span class="n">rpc</span><span class="p">.</span><span class="n">startFlow</span><span class="p">(</span><span class="o">::</span><span class="n">FinalityFlow</span><span class="p">,</span> <span class="n">stx</span><span class="p">,</span> <span class="n">setOf</span><span class="p">(</span><span class="n">otherSide</span><span class="p">))</span>
<span class="n">protocolHandle</span><span class="p">.</span><span class="n">progress</span><span class="p">.</span><span class="n">subscribe</span><span class="p">(</span><span class="o">::</span><span class="n">println</span><span class="p">)</span>
<span class="n">protocolHandle</span><span class="p">.</span><span class="n">returnValue</span><span class="p">.</span><span class="n">toBlocking</span><span class="p">().</span><span class="n">first</span><span class="p">()</span>
<span class="p">}</span>
</pre></div>
</div>
<p>This side is a bit more complex. Firstly it looks up its counterparty by name in the network map. Then, if the node
doesn&#8217;t already have the attachment in its storage, we upload it from a JAR resource and check the hash was what
we expected. Then a trivial transaction is built that has the attachment and a single signature and it&#8217;s sent to
the other side using the FinalityFlow. The result of starting the flow is a stream of progress messages and a
<code class="docutils literal"><span class="pre">returnValue</span></code> observable that can be used to watch out for the flow completing successfully.</p>
</div>
</div>