corda/docs/build/html/tutorial-attachments.html
2017-01-06 17:38:23 +00:00

375 lines
22 KiB
HTML

<!-- If you edit this, then please make the same changes to layout_for_doc_website.html, as that is used for the web
doc site generation which we put analytics tracking on to identify any potential problem pages -->
<!DOCTYPE html>
<!--[if IE 8]><html class="no-js lt-ie9" lang="en" > <![endif]-->
<!--[if gt IE 8]><!--> <html class="no-js" lang="en" > <!--<![endif]-->
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Using attachments &mdash; R3 Corda latest documentation</title>
<link rel="stylesheet" href="_static/css/custom.css" type="text/css" />
<link rel="top" title="R3 Corda latest documentation" href="index.html"/>
<link rel="next" title="Event scheduling" href="event-scheduling.html"/>
<link rel="prev" title="Writing oracle services" href="oracles.html"/>
<script src="_static/js/modernizr.min.js"></script>
</head>
<body class="wy-body-for-nav" role="document">
<div class="wy-grid-for-nav">
<nav data-toggle="wy-nav-shift" class="wy-nav-side">
<div class="wy-side-scroll">
<div class="wy-side-nav-search">
<a href="index.html" class="icon icon-home"> R3 Corda
</a>
<div class="version">
latest
</div>
<div role="search">
<form id="rtd-search-form" class="wy-form" action="search.html" method="get">
<input type="text" name="q" placeholder="Search docs" />
<input type="hidden" name="check_keywords" value="yes" />
<input type="hidden" name="area" value="default" />
</form>
</div>
<br>
<a href="api/index.html">API reference</a>
<br>
<a href="https://discourse.corda.net">Discourse Forums</a>
<br>
<a href="http://slack.corda.net">Slack</a>
<br>
</div>
<div class="wy-menu wy-menu-vertical" data-spy="affix" role="navigation" aria-label="main navigation">
<p class="caption"><span class="caption-text">Getting started</span></p>
<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">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>
<p class="caption"><span class="caption-text">Key concepts</span></p>
<ul>
<li class="toctree-l1"><a class="reference internal" href="data-model.html">Data model</a></li>
<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</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">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>
<li class="toctree-l1"><a class="reference internal" href="clientrpc.html">Client RPC</a></li>
<li class="toctree-l1"><a class="reference internal" href="messaging.html">Networking and messaging</a></li>
<li class="toctree-l1"><a class="reference internal" href="persistence.html">Persistence</a></li>
<li class="toctree-l1"><a class="reference internal" href="node-administration.html">Node administration</a></li>
<li class="toctree-l1"><a class="reference internal" href="corda-configuration-file.html">Node configuration</a></li>
<li class="toctree-l1"><a class="reference internal" href="corda-plugins.html">The Corda plugin framework</a></li>
<li class="toctree-l1"><a class="reference internal" href="node-services.html">Brief introduction to the node services</a></li>
<li class="toctree-l1"><a class="reference internal" href="node-explorer.html">Node Explorer</a></li>
<li class="toctree-l1"><a class="reference internal" href="permissioning.html">Network permissioning</a></li>
</ul>
<p class="caption"><span class="caption-text">Tutorials</span></p>
<ul class="current">
<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 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="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 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>
</li>
<li class="toctree-l1"><a class="reference internal" href="event-scheduling.html">Event scheduling</a></li>
</ul>
<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>
</ul>
<p class="caption"><span class="caption-text">Component library</span></p>
<ul>
<li class="toctree-l1"><a class="reference internal" href="contract-catalogue.html">Contract catalogue</a></li>
<li class="toctree-l1"><a class="reference internal" href="contract-irs.html">Interest rate swaps</a></li>
</ul>
<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">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-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>
<li class="toctree-l1"><a class="reference internal" href="publishing-corda.html">Publishing Corda</a></li>
<li class="toctree-l1"><a class="reference internal" href="azure-vm.html">Working with the Corda Demo on Azure Marketplace</a></li>
</ul>
<p class="caption"><span class="caption-text">Glossary</span></p>
<ul>
<li class="toctree-l1"><a class="reference internal" href="glossary.html">Glossary</a></li>
</ul>
</div>
</div>
</nav>
<section data-toggle="wy-nav-shift" class="wy-nav-content-wrap">
<nav class="wy-nav-top" role="navigation" aria-label="top navigation">
<i data-toggle="wy-nav-top" class="fa fa-bars"></i>
<a href="index.html">R3 Corda</a>
</nav>
<div class="wy-nav-content">
<div class="rst-content">
<div role="navigation" aria-label="breadcrumbs navigation">
<ul class="wy-breadcrumbs">
<li><a href="index.html">Docs</a> &raquo;</li>
<li>Using attachments</li>
<li class="wy-breadcrumbs-aside">
<a href="_sources/tutorial-attachments.txt" rel="nofollow"> View page source</a>
</li>
</ul>
<hr/>
</div>
<div role="main" class="document" itemscope="itemscope" itemtype="http://schema.org/Article">
<div itemprop="articleBody">
<div class="section" id="using-attachments">
<h1>Using attachments<a class="headerlink" href="#using-attachments" title="Permalink to this headline"></a></h1>
<p>Attachments are (typically large) Zip/Jar files referenced within a transaction, but not included in the transaction
itself. These files can be requested from the originating node as needed, although in many cases will be cached within
nodes already. Examples include:</p>
<ul class="simple">
<li>Contract executable code</li>
<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 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
<code class="docutils literal"><span class="pre">FetchTransactionsFlow</span></code> to perform the actual retrieval.</p>
<p>It is encouraged that where possible attachments are reusable data, so that nodes can meaningfully cache them.</p>
<div class="section" id="attachments-demo">
<h2>Attachments demo<a class="headerlink" href="#attachments-demo" title="Permalink to this headline"></a></h2>
<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 <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">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="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>
<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">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">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>
</div>
</div>
<footer>
<div class="rst-footer-buttons" role="navigation" aria-label="footer navigation">
<a href="event-scheduling.html" class="btn btn-neutral float-right" title="Event scheduling" accesskey="n">Next <span class="fa fa-arrow-circle-right"></span></a>
<a href="oracles.html" class="btn btn-neutral" title="Writing oracle services" accesskey="p"><span class="fa fa-arrow-circle-left"></span> Previous</a>
</div>
<hr/>
<div role="contentinfo">
<p>
&copy; Copyright 2016, R3 Limited.
</p>
</div>
Built with <a href="http://sphinx-doc.org/">Sphinx</a> using a <a href="https://github.com/snide/sphinx_rtd_theme">theme</a> provided by <a href="https://readthedocs.org">Read the Docs</a>.
</footer>
</div>
</div>
</section>
</div>
<script type="text/javascript">
var DOCUMENTATION_OPTIONS = {
URL_ROOT:'./',
VERSION:'latest',
COLLAPSE_INDEX:false,
FILE_SUFFIX:'.html',
HAS_SOURCE: true
};
</script>
<script type="text/javascript" src="_static/jquery.js"></script>
<script type="text/javascript" src="_static/underscore.js"></script>
<script type="text/javascript" src="_static/doctools.js"></script>
<script type="text/javascript" src="_static/js/theme.js"></script>
<script type="text/javascript">
jQuery(function () {
SphinxRtdTheme.StickyNav.enable();
});
</script>
</body>
</html>