corda/docs/build/html/using-a-notary.html

409 lines
26 KiB
HTML
Raw Normal View History

2017-01-03 13:07:48 +00:00
<!-- 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 -->
2016-11-29 11:38:52 +00:00
<!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 a notary service &mdash; R3 Corda latest documentation</title>
<link rel="stylesheet" href="_static/css/custom.css" type="text/css" />
2017-02-08 16:08:46 +00:00
<link rel="index" title="Index"
href="genindex.html"/>
<link rel="search" title="Search" href="search.html"/>
2016-11-29 11:38:52 +00:00
<link rel="top" title="R3 Corda latest documentation" href="index.html"/>
<link rel="next" title="Writing oracle services" href="oracles.html"/>
<link rel="prev" title="Running a notary service" href="running-a-notary.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>
API reference: <a href="api/kotlin/corda/index.html">Kotlin</a>/ <a href="api/javadoc/index.html">JavaDoc</a>
2017-01-03 13:07:48 +00:00
<br>
<a href="https://discourse.corda.net">Discourse Forums</a>
<br>
<a href="http://slack.corda.net">Slack</a>
<br>
2016-11-29 11:38:52 +00:00
</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>
2017-01-06 17:38:23 +00:00
<li class="toctree-l1"><a class="reference internal" href="getting-set-up-fault-finding.html">Troubleshooting</a></li>
2016-11-29 11:38:52 +00:00
<li class="toctree-l1"><a class="reference internal" href="running-the-demos.html">Running the demos</a></li>
2016-11-29 18:44:59 +00:00
<li class="toctree-l1"><a class="reference internal" href="CLI-vs-IDE.html">CLI vs IDE</a></li>
2016-11-29 11:38:52 +00:00
</ul>
<p class="caption"><span class="caption-text">Key concepts</span></p>
<ul>
<li class="toctree-l1"><a class="reference internal" href="key-concepts.html">Overview</a></li>
<li class="toctree-l1"><a class="reference internal" href="key-concepts-ecosystem.html">Corda ecosystem</a></li>
<li class="toctree-l1"><a class="reference internal" href="key-concepts-data-model.html">Data model</a></li>
<li class="toctree-l1"><a class="reference internal" href="key-concepts-core-types.html">Core types</a></li>
<li class="toctree-l1"><a class="reference internal" href="key-concepts-financial-model.html">Financial model</a></li>
<li class="toctree-l1"><a class="reference internal" href="key-concepts-flow-framework.html">Flow framework</a></li>
<li class="toctree-l1"><a class="reference internal" href="key-concepts-consensus-notaries.html">Consensus and notaries</a></li>
<li class="toctree-l1"><a class="reference internal" href="key-concepts-vault.html">Vault</a></li>
<li class="toctree-l1"><a class="reference internal" href="key-concepts-security-model.html">Security model</a></li>
2016-11-29 18:44:59 +00:00
</ul>
<p class="caption"><span class="caption-text">CorDapps</span></p>
<ul>
2017-01-06 17:38:23 +00:00
<li class="toctree-l1"><a class="reference internal" href="creating-a-cordapp.html">CorDapp basics</a></li>
2017-02-08 16:08:46 +00:00
<li class="toctree-l1"><a class="reference internal" href="tutorial-cordapp.html">The example CorDapp</a></li>
2016-11-29 11:38:52 +00:00
</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>
2017-01-06 17:38:23 +00:00
<li class="toctree-l1"><a class="reference internal" href="tutorial-integration-testing.html">Integration testing</a></li>
2016-11-29 11:38:52 +00:00
<li class="toctree-l1"><a class="reference internal" href="tutorial-clientrpc-api.html">Client RPC API tutorial</a></li>
2017-01-06 17:38:23 +00:00
<li class="toctree-l1"><a class="reference internal" href="tutorial-building-transactions.html">Building transactions</a></li>
2016-11-29 11:38:52 +00:00
<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 current"><a class="current reference internal" href="#">Using a notary service</a><ul>
<li class="toctree-l2"><a class="reference internal" href="#assigning-a-notary">Assigning a notary</a></li>
<li class="toctree-l2"><a class="reference internal" href="#notarising-a-transaction">Notarising a transaction</a></li>
</ul>
</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="tutorial-attachments.html">Using attachments</a></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>
<li class="toctree-l1"><a class="reference internal" href="clauses.html">Clauses</a></li>
<li class="toctree-l1"><a class="reference internal" href="merkle-trees.html">Transaction tear-offs</a></li>
2016-11-29 11:38:52 +00:00
</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>
2017-01-06 17:38:23 +00:00
<li class="toctree-l1"><a class="reference internal" href="setting-up-a-corda-network.html">What is a corda network?</a></li>
2016-11-29 11:38:52 +00:00
<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="further-notes-on-kotlin.html">Further notes on Kotlin</a></li>
2017-01-03 13:07:48 +00:00
<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>
2016-11-29 11:38:52 +00:00
</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 a notary service</li>
<li class="wy-breadcrumbs-aside">
<a href="_sources/using-a-notary.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-a-notary-service">
<h1>Using a notary service<a class="headerlink" href="#using-a-notary-service" title="Permalink to this headline"></a></h1>
<p>This tutorial describes how to assign a notary to a newly issued state, and how to get a transaction notarised by
obtaining a signature of the required notary. It assumes some familiarity with <em>flows</em> and how to write them, as described
in <a class="reference internal" href="flow-state-machines.html"><span class="doc">Writing flows</span></a>.</p>
<div class="section" id="assigning-a-notary">
<h2>Assigning a notary<a class="headerlink" href="#assigning-a-notary" title="Permalink to this headline"></a></h2>
<p>The first step is to choose a notary and obtain its identity. Identities of all notaries on the network are kept by
the <a class="reference internal" href="messaging.html#network-map-service"><span class="std std-ref">Network Map Service</span></a>. The network map cache exposes two methods for obtaining a notary:</p>
<div class="highlight-kotlin"><div class="highlight"><pre><span></span><span class="cm">/**</span>
<span class="cm"> * Gets a notary identity by the given name.</span>
<span class="cm"> */</span>
<span class="k">fun</span> <span class="nf">getNotary</span><span class="p">(</span><span class="n">name</span><span class="p">:</span> <span class="n">String</span><span class="p">):</span> <span class="n">Party</span><span class="p">?</span>
<span class="cm">/**</span>
<span class="cm"> * Returns a notary identity advertised by any of the nodes on the network (chosen at random)</span>
<span class="cm"> *</span>
<span class="cm"> * @param type Limits the result to notaries of the specified type (optional)</span>
<span class="cm"> */</span>
<span class="k">fun</span> <span class="nf">getAnyNotary</span><span class="p">(</span><span class="n">type</span><span class="p">:</span> <span class="n">ServiceType</span><span class="p">?</span> <span class="p">=</span> <span class="k">null</span><span class="p">):</span> <span class="n">Party</span><span class="p">?</span>
</pre></div>
</div>
<p>Currently notaries can only be differentiated by name and type, but in the future the network map service will be
able to provide more metadata, such as location or legal identities of the nodes operating it.</p>
<p>Now, let&#8217;s say we want to issue an asset and assign it to a notary named &#8220;Notary A&#8221;.
The first step is to obtain the notary identity &#8211; <code class="docutils literal"><span class="pre">Party</span></code>:</p>
<div class="highlight-kotlin"><div class="highlight"><pre><span></span><span class="k">val</span> <span class="py">ourNotary</span><span class="p">:</span> <span class="n">Party</span> <span class="p">=</span> <span class="n">serviceHub</span><span class="p">.</span><span class="n">networkMapCache</span><span class="p">.</span><span class="n">getNotary</span><span class="p">(</span><span class="s">&quot;Central Bank Notary&quot;</span><span class="p">)</span>
</pre></div>
</div>
<p>Then we initialise the transaction builder:</p>
<div class="highlight-kotlin"><div class="highlight"><pre><span></span><span class="k">val</span> <span class="py">builder</span><span class="p">:</span> <span class="n">TransactionBuilder</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="n">ourNotary</span><span class="p">)</span>
</pre></div>
</div>
<p>For any output state we add to this transaction builder, <code class="docutils literal"><span class="pre">ourNotary</span></code> will be assigned as its notary.
Next we create a state object and assign ourselves as the owner. For this example we&#8217;ll use a
<code class="docutils literal"><span class="pre">DummyContract.State</span></code>, which is a simple state that just maintains an integer and can change ownership.</p>
<div class="highlight-kotlin"><div class="highlight"><pre><span></span><span class="k">val</span> <span class="py">myIdentity</span> <span class="p">=</span> <span class="n">serviceHub</span><span class="p">.</span><span class="n">myInfo</span><span class="p">.</span><span class="n">legalIdentity</span>
<span class="k">val</span> <span class="py">state</span> <span class="p">=</span> <span class="n">DummyContract</span><span class="p">.</span><span class="n">SingleOwnerState</span><span class="p">(</span><span class="n">magicNumber</span> <span class="p">=</span> <span class="m">42</span><span class="p">,</span> <span class="n">owner</span> <span class="p">=</span> <span class="n">myIdentity</span><span class="p">.</span><span class="n">owningKey</span><span class="p">)</span>
</pre></div>
</div>
<p>Then we add the state as the transaction output along with the relevant command. The state will automatically be assigned
to our previously specified &#8220;Notary A&#8221;.</p>
<div class="highlight-kotlin"><div class="highlight"><pre><span></span><span class="n">builder</span><span class="p">.</span><span class="n">addOutputState</span><span class="p">(</span><span class="n">state</span><span class="p">)</span>
<span class="k">val</span> <span class="py">createCommand</span> <span class="p">=</span> <span class="n">DummyContract</span><span class="p">.</span><span class="n">Commands</span><span class="p">.</span><span class="n">Create</span><span class="p">()</span>
<span class="n">builder</span><span class="p">.</span><span class="n">addCommand</span><span class="p">(</span><span class="n">Command</span><span class="p">(</span><span class="n">createCommand</span><span class="p">,</span> <span class="n">myIdentity</span><span class="p">))</span>
</pre></div>
</div>
<p>We then sign the transaction, build and record it to our transaction storage:</p>
<div class="highlight-kotlin"><div class="highlight"><pre><span></span><span class="k">val</span> <span class="py">mySigningKey</span><span class="p">:</span> <span class="n">KeyPair</span> <span class="p">=</span> <span class="n">serviceHub</span><span class="p">.</span><span class="n">legalIdentityKey</span>
<span class="n">builder</span><span class="p">.</span><span class="n">signWith</span><span class="p">(</span><span class="n">mySigningKey</span><span class="p">)</span>
<span class="k">val</span> <span class="py">issueTransaction</span> <span class="p">=</span> <span class="n">builder</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">recordTransactions</span><span class="p">(</span><span class="n">issueTransaction</span><span class="p">)</span>
</pre></div>
</div>
<p>The transaction is recorded and we now have a state (asset) in possession that we can transfer to someone else. Note
that the issuing transaction does not need to be notarised, as it doesn&#8217;t consume any input states.</p>
</div>
<div class="section" id="notarising-a-transaction">
<h2>Notarising a transaction<a class="headerlink" href="#notarising-a-transaction" title="Permalink to this headline"></a></h2>
<p>Following our example for the previous section, let&#8217;s say we now want to transfer our issued state to Alice.</p>
<p>First we obtain a reference to the state, which will be the input to our &#8220;move&#8221; transaction:</p>
<div class="highlight-kotlin"><div class="highlight"><pre><span></span><span class="k">val</span> <span class="py">stateRef</span> <span class="p">=</span> <span class="n">StateRef</span><span class="p">(</span><span class="n">txhash</span> <span class="p">=</span> <span class="n">issueTransaction</span><span class="p">.</span><span class="n">id</span><span class="p">,</span> <span class="n">index</span> <span class="p">=</span> <span class="m">0</span><span class="p">)</span>
</pre></div>
</div>
<p>Then we create a new state &#8211; a copy of our state but with the owner set to Alice. This is a bit more involved so
we just use a helper that handles it for us. We also assume that we already have the <code class="docutils literal"><span class="pre">Party</span></code> for Alice, <code class="docutils literal"><span class="pre">aliceParty</span></code>.</p>
<div class="highlight-kotlin"><div class="highlight"><pre><span></span><span class="k">val</span> <span class="py">inputState</span> <span class="p">=</span> <span class="n">StateAndRef</span><span class="p">(</span><span class="n">sate</span><span class="p">,</span> <span class="n">stateRef</span><span class="p">)</span>
<span class="k">val</span> <span class="py">moveTransactionBuilder</span> <span class="p">=</span> <span class="n">DummyContract</span><span class="p">.</span><span class="n">move</span><span class="p">(</span><span class="n">inputState</span><span class="p">,</span> <span class="n">newOwner</span> <span class="p">=</span> <span class="n">aliceParty</span><span class="p">.</span><span class="n">owningKey</span><span class="p">)</span>
</pre></div>
</div>
<p>The <code class="docutils literal"><span class="pre">DummyContract.move()</span></code> method will a new transaction builder with our old state as the input, a new state
with Alice as the owner, and a relevant contract command for &#8220;move&#8221;.</p>
<p>Again we sign the transaction, and build it:</p>
<div class="highlight-kotlin"><div class="highlight"><pre><span></span><span class="n">moveTransactionBuilder</span><span class="p">.</span><span class="n">signWith</span><span class="p">(</span><span class="n">mySigningKey</span><span class="p">)</span>
<span class="c1">// We build it without checking if all signatures are present, because we know that the notary signature is missing</span>
<span class="k">val</span> <span class="py">moveTransaction</span> <span class="p">=</span> <span class="n">builder</span><span class="p">.</span><span class="n">toSignedTransaction</span><span class="p">(</span><span class="n">checkSufficientSignatures</span> <span class="p">=</span> <span class="k">false</span><span class="p">)</span>
</pre></div>
</div>
<p>Next we need to obtain a signature from the notary for the transaction to be valid. Prior to signing, the notary will
commit our old (input) state so it cannot be used again.</p>
<p>To manually obtain a signature from a notary we can run the <code class="docutils literal"><span class="pre">NotaryFlow.Client</span></code> flow. The flow will work out
which notary needs to be called based on the input states (and the timestamp command, if it&#8217;s present).</p>
<div class="highlight-kotlin"><div class="highlight"><pre><span></span><span class="c1">// The subFlow() helper is available within the context of a Flow</span>
<span class="k">val</span> <span class="py">notarySignature</span><span class="p">:</span> <span class="n">DigitalSignature</span> <span class="p">=</span> <span class="n">subFlow</span><span class="p">(</span><span class="n">NotaryFlow</span><span class="p">.</span><span class="n">Client</span><span class="p">(</span><span class="n">moveTransaction</span><span class="p">))</span>
</pre></div>
</div>
<div class="admonition note">
<p class="first admonition-title">Note</p>
<p>If our input state has already been consumed in another transaction, then <code class="docutils literal"><span class="pre">NotaryFlow</span></code> with throw a <code class="docutils literal"><span class="pre">NotaryException</span></code>
containing the conflict details:</p>
<div class="highlight-kotlin"><div class="highlight"><pre><span></span><span class="cm">/** Specifies the consuming transaction for the conflicting input state */</span>
<span class="k">data</span> <span class="k">class</span> <span class="nc">Conflict</span><span class="p">(</span><span class="k">val</span> <span class="py">stateHistory</span><span class="p">:</span> <span class="n">Map</span><span class="p">&lt;</span><span class="n">StateRef</span><span class="p">,</span> <span class="n">ConsumingTx</span><span class="p">&gt;)</span>
<span class="cm">/**</span>
<span class="cm">* Specifies the transaction id, the position of the consumed state in the inputs, and</span>
<span class="cm">* the caller identity requesting the commit</span>
<span class="cm">*/</span>
<span class="k">data</span> <span class="k">class</span> <span class="nc">ConsumingTx</span><span class="p">(</span><span class="k">val</span> <span class="py">id</span><span class="p">:</span> <span class="n">SecureHash</span><span class="p">,</span> <span class="k">val</span> <span class="py">inputIndex</span><span class="p">:</span> <span class="n">Int</span><span class="p">,</span> <span class="k">val</span> <span class="py">requestingParty</span><span class="p">:</span> <span class="n">Party</span><span class="p">)</span>
</pre></div>
</div>
<p class="last">Conflict handling and resolution is currently the responsibility of the flow author.</p>
</div>
<p>Note that instead of calling the notary directly, we would normally call <code class="docutils literal"><span class="pre">FinalityFlow</span></code> passing in the <code class="docutils literal"><span class="pre">SignedTransaction</span></code>
(including signatures from the participants) and a list of participants to notify. The flow will request a notary signature
if needed, record the notarised transaction, and then send a copy of the transaction to all participants for them to store.
<code class="docutils literal"><span class="pre">FinalityFlow</span></code> delegates to <code class="docutils literal"><span class="pre">NotaryFlow.Client</span></code> followed by <code class="docutils literal"><span class="pre">BroadcastTransactionFlow</span></code> to do the
actual work of notarising and broadcasting the transaction. For example:</p>
<div class="highlight-kotlin"><div class="highlight"><pre><span></span><span class="n">subFlow</span><span class="p">(</span><span class="n">FinalityFlow</span><span class="p">(</span><span class="n">moveTransaction</span><span class="p">,</span> <span class="n">setOf</span><span class="p">(</span><span class="n">aliceParty</span><span class="p">))</span>
</pre></div>
</div>
</div>
</div>
</div>
</div>
<footer>
<div class="rst-footer-buttons" role="navigation" aria-label="footer navigation">
<a href="oracles.html" class="btn btn-neutral float-right" title="Writing oracle services" accesskey="n">Next <span class="fa fa-arrow-circle-right"></span></a>
<a href="running-a-notary.html" class="btn btn-neutral" title="Running a notary service" accesskey="p"><span class="fa fa-arrow-circle-left"></span> Previous</a>
</div>
<hr/>
<div role="contentinfo">
<p>
2016-11-29 18:44:59 +00:00
&copy; Copyright 2016, R3 Limited.
2016-11-29 11:38:52 +00:00
</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>