corda/docs/build/html/protocol-state-machines.html

769 lines
62 KiB
HTML
Raw Normal View History

2015-12-14 17:22:34 +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">
2016-05-09 16:13:23 +00:00
<title>Protocol state machines &mdash; R3 Corda latest documentation</title>
2015-12-14 17:22:34 +00:00
<link rel="stylesheet" href="_static/css/custom.css" type="text/css" />
2016-05-09 16:13:23 +00:00
<link rel="top" title="R3 Corda latest documentation" href="index.html"/>
2016-03-15 16:13:01 +00:00
<link rel="next" title="Writing oracle services" href="oracles.html"/>
2016-07-12 16:52:52 +00:00
<link rel="prev" title="Writing a contract test" href="tutorial-test-dsl.html"/>
2015-12-14 17:22:34 +00:00
<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">
2015-12-14 17:22:34 +00:00
2016-05-09 16:13:23 +00:00
<a href="index.html" class="icon icon-home"> R3 Corda
2015-12-14 17:22:34 +00:00
</a>
<div class="version">
2016-02-25 12:29:28 +00:00
latest
2015-12-14 17:22:34 +00:00
</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>
2015-12-14 17:22:34 +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">Overview</span></p>
<ul>
2015-12-14 17:22:34 +00:00
<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="data-model.html">Data model</a></li>
2016-06-30 12:49:28 +00:00
<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="consensus.html">Consensus model</a></li>
2015-12-14 17:22:34 +00:00
<li class="toctree-l1"><a class="reference internal" href="messaging.html">Networking and messaging</a></li>
2016-05-09 16:13:23 +00:00
<li class="toctree-l1"><a class="reference internal" href="running-the-demos.html">Running the demos</a></li>
2016-03-04 15:15:51 +00:00
<li class="toctree-l1"><a class="reference internal" href="node-administration.html">Node administration</a></li>
2016-08-09 10:21:07 +00:00
</ul>
<p class="caption"><span class="caption-text">Contracts</span></p>
<ul>
<li class="toctree-l1"><a class="reference internal" href="contract-catalogue.html">Platform contracts</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">Tutorials</span></p>
<ul class="current">
2016-05-24 11:27:23 +00:00
<li class="toctree-l1"><a class="reference internal" href="where-to-start.html">Where to start</a></li>
<li class="toctree-l1"><a class="reference internal" href="tutorial-contract.html">Writing a contract</a></li>
2016-07-12 16:52:52 +00:00
<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>
2016-04-13 09:29:54 +00:00
<li class="toctree-l1 current"><a class="current reference internal" href="#">Protocol state machines</a><ul>
2015-12-14 17:22:34 +00:00
<li class="toctree-l2"><a class="reference internal" href="#introduction">Introduction</a></li>
<li class="toctree-l2"><a class="reference internal" href="#theory">Theory</a></li>
<li class="toctree-l2"><a class="reference internal" href="#a-two-party-trading-protocol">A two party trading protocol</a></li>
<li class="toctree-l2"><a class="reference internal" href="#suspendable-methods">Suspendable methods</a></li>
2015-12-14 17:22:34 +00:00
<li class="toctree-l2"><a class="reference internal" href="#the-state-machine-manager">The state machine manager</a></li>
<li class="toctree-l2"><a class="reference internal" href="#implementing-the-seller">Implementing the seller</a></li>
<li class="toctree-l2"><a class="reference internal" href="#implementing-the-buyer">Implementing the buyer</a></li>
2016-02-25 12:29:28 +00:00
<li class="toctree-l2"><a class="reference internal" href="#progress-tracking">Progress tracking</a></li>
2015-12-14 17:22:34 +00:00
</ul>
</li>
2016-03-15 16:13:01 +00:00
<li class="toctree-l1"><a class="reference internal" href="oracles.html">Writing oracle services</a></li>
2016-06-30 12:49:28 +00:00
<li class="toctree-l1"><a class="reference internal" href="event-scheduling.html">Event scheduling</a></li>
</ul>
<p class="caption"><span class="caption-text">Appendix</span></p>
<ul>
2016-05-24 11:27:23 +00:00
<li class="toctree-l1"><a class="reference internal" href="release-process.html">Release process</a></li>
2016-06-13 17:27:53 +00:00
<li class="toctree-l1"><a class="reference internal" href="release-process.html#steps-to-cut-a-release">Steps to cut a release</a></li>
2016-05-24 11:27:23 +00:00
<li class="toctree-l1"><a class="reference internal" href="release-notes.html">Release notes</a></li>
2015-12-14 17:22:34 +00:00
<li class="toctree-l1"><a class="reference internal" href="visualiser.html">Using the visualiser</a></li>
2016-01-27 15:01:52 +00:00
<li class="toctree-l1"><a class="reference internal" href="codestyle.html">Code style guide</a></li>
2016-05-09 16:13:23 +00:00
<li class="toctree-l1"><a class="reference internal" href="building-the-docs.html">Building the documentation</a></li>
2015-12-14 17:22:34 +00:00
</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>
2016-05-09 16:13:23 +00:00
<a href="index.html">R3 Corda</a>
2015-12-14 17:22:34 +00:00
</nav>
<div class="wy-nav-content">
<div class="rst-content">
2016-04-13 09:29:54 +00:00
2015-12-14 17:22:34 +00:00
<div role="navigation" aria-label="breadcrumbs navigation">
<ul class="wy-breadcrumbs">
<li><a href="index.html">Docs</a> &raquo;</li>
<li>Protocol state machines</li>
<li class="wy-breadcrumbs-aside">
<a href="_sources/protocol-state-machines.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">
<script type="text/javascript" src="_static/jquery.js"></script>
<script type="text/javascript" src="_static/codesets.js"></script><div class="section" id="protocol-state-machines">
<h1>Protocol state machines<a class="headerlink" href="#protocol-state-machines" title="Permalink to this headline"></a></h1>
<p>This article explains our experimental approach to modelling financial protocols in code. It explains how the
platform&#8217;s state machine framework is used, and takes you through the code for a simple 2-party asset trading protocol
which is included in the source.</p>
<div class="section" id="introduction">
<h2>Introduction<a class="headerlink" href="#introduction" title="Permalink to this headline"></a></h2>
<p>Shared distributed ledgers are interesting because they allow many different, mutually distrusting parties to
share a single source of truth about the ownership of assets. Digitally signed transactions are used to update that
shared ledger, and transactions may alter many states simultaneously and atomically.</p>
<p>Blockchain systems such as Bitcoin support the idea of building up a finished, signed transaction by passing around
partially signed invalid transactions outside of the main network, and by doing this you can implement
<em>delivery versus payment</em> such that there is no chance of settlement failure, because the movement of cash and the
traded asset are performed atomically by the same transaction. To perform such a trade involves a multi-step protocol
in which messages are passed back and forth privately between parties, checked, signed and so on.</p>
<p>Despite how useful these protocols are, platforms such as Bitcoin and Ethereum do not assist the developer with the rather
tricky task of actually building them. That is unfortunate. There are many awkward problems in their implementation
that a good platform would take care of for you, problems like:</p>
<ul class="simple">
<li>Avoiding &#8220;callback hell&#8221; in which code that should ideally be sequential is turned into an unreadable mess due to the
desire to avoid using up a thread for every protocol instantiation.</li>
<li>Surviving node shutdowns/restarts that may occur in the middle of the protocol without complicating things. This
implies that the state of the protocol must be persisted to disk.</li>
<li>Error handling.</li>
<li>Message routing.</li>
<li>Serialisation.</li>
<li>Catching type errors, in which the developer gets temporarily confused and expects to receive/send one type of message
when actually they need to receive/send another.</li>
<li>Unit testing of the finished protocol.</li>
</ul>
<p>Actor frameworks can solve some of the above but they are often tightly bound to a particular messaging layer, and
we would like to keep a clean separation. Additionally, they are typically not type safe, and don&#8217;t make persistence or
writing sequential code much easier.</p>
<p>To put these problems in perspective, the <em>payment channel protocol</em> in the bitcoinj library, which allows bitcoins to
2015-12-14 17:22:34 +00:00
be temporarily moved off-chain and traded at high speed between two parties in private, consists of about 7000 lines of
Java and took over a month of full time work to develop. Most of that code is concerned with the details of persistence,
message passing, lifecycle management, error handling and callback management. Because the business logic is quite
spread out the code can be difficult to read and debug.</p>
<p>As small contract-specific trading protocols are a common occurence in finance, we provide a framework for the
construction of them that automatically handles many of the concerns outlined above.</p>
</div>
<div class="section" id="theory">
<h2>Theory<a class="headerlink" href="#theory" title="Permalink to this headline"></a></h2>
<p>A <em>continuation</em> is a suspended stack frame stored in a regular object that can be passed around, serialised,
unserialised and resumed from where it was suspended. This concept is sometimes referred to as &#8220;fibers&#8221;. This may
sound abstract but don&#8217;t worry, the examples below will make it clearer. The JVM does not natively support
continuations, so we implement them using a library called Quasar which works through behind-the-scenes
bytecode rewriting. You don&#8217;t have to know how this works to benefit from it, however.</p>
2015-12-14 17:22:34 +00:00
<p>We use continuations for the following reasons:</p>
<ul class="simple">
<li>It allows us to write code that is free of callbacks, that looks like ordinary sequential code.</li>
<li>A suspended continuation takes far less memory than a suspended thread. It can be as low as a few hundred bytes.
2016-02-25 12:29:28 +00:00
In contrast a suspended Java thread stack can easily be 1mb in size.</li>
2015-12-14 17:22:34 +00:00
<li>It frees the developer from thinking (much) about persistence and serialisation.</li>
</ul>
<p>A <em>state machine</em> is a piece of code that moves through various <em>states</em>. These are not the same as states in the data
model (that represent facts about the world on the ledger), but rather indicate different stages in the progression
of a multi-stage protocol. Typically writing a state machine would require the use of a big switch statement and some
explicit variables to keep track of where you&#8217;re up to. The use of continuations avoids this hassle.</p>
</div>
<div class="section" id="a-two-party-trading-protocol">
<h2>A two party trading protocol<a class="headerlink" href="#a-two-party-trading-protocol" title="Permalink to this headline"></a></h2>
<p>We would like to implement the &#8220;hello world&#8221; of shared transaction building protocols: a seller wishes to sell some
<em>asset</em> (e.g. some commercial paper) in return for <em>cash</em>. The buyer wishes to purchase the asset using his cash. They
want the trade to be atomic so neither side is exposed to the risk of settlement failure. We assume that the buyer
and seller have found each other and arranged the details on some exchange, or over the counter. The details of how
the trade is arranged isn&#8217;t covered in this article.</p>
<p>Our protocol has two parties (B and S for buyer and seller) and will proceed as follows:</p>
<ol class="arabic simple">
<li>S sends a <code class="docutils literal"><span class="pre">StateAndRef</span></code> pointing to the state they want to sell to B, along with info about the price they require
B to pay.</li>
2016-02-25 12:29:28 +00:00
<li>B sends to S a <code class="docutils literal"><span class="pre">SignedTransaction</span></code> that includes the state as input, B&#8217;s cash as input, the state with the new
2015-12-14 17:22:34 +00:00
owner key as output, and any change cash as output. It contains a single signature from B but isn&#8217;t valid because
it lacks a signature from S authorising movement of the asset.</li>
2016-02-25 12:29:28 +00:00
<li>S signs it and hands the now finalised <code class="docutils literal"><span class="pre">SignedTransaction</span></code> back to B.</li>
2015-12-14 17:22:34 +00:00
</ol>
<p>You can find the implementation of this protocol in the file <code class="docutils literal"><span class="pre">contracts/protocols/TwoPartyTradeProtocol.kt</span></code>.</p>
<p>Assuming no malicious termination, they both end the protocol being in posession of a valid, signed transaction that
represents an atomic asset swap.</p>
<p>Note that it&#8217;s the <em>seller</em> who initiates contact with the buyer, not vice-versa as you might imagine.</p>
<p>We start by defining a wrapper that namespaces the protocol code, two functions to start either the buy or sell side
of the protocol, and two classes that will contain the protocol definition. We also pick what data will be used by
each side.</p>
2015-12-14 17:22:34 +00:00
<div class="codeset container">
2016-04-13 09:29:54 +00:00
<div class="highlight-kotlin"><div class="highlight"><pre><span></span><span class="k">object</span> <span class="nc">TwoPartyTradeProtocol</span> <span class="p">{</span>
<span class="k">val</span> <span class="py">TRADE_TOPIC</span> <span class="p">=</span> <span class="s">&quot;platform.trade&quot;</span>
<span class="k">fun</span> <span class="nf">runSeller</span><span class="p">(</span><span class="n">smm</span><span class="p">:</span> <span class="n">StateMachineManager</span><span class="p">,</span> <span class="n">timestampingAuthority</span><span class="p">:</span> <span class="n">LegallyIdentifiableNode</span><span class="p">,</span>
<span class="n">otherSide</span><span class="p">:</span> <span class="n">SingleMessageRecipient</span><span class="p">,</span> <span class="n">assetToSell</span><span class="p">:</span> <span class="n">StateAndRef</span><span class="p">&lt;</span><span class="n">OwnableState</span><span class="p">&gt;,</span> <span class="n">price</span><span class="p">:</span> <span class="n">Amount</span><span class="p">,</span>
2016-02-25 12:29:28 +00:00
<span class="n">myKeyPair</span><span class="p">:</span> <span class="n">KeyPair</span><span class="p">,</span> <span class="n">buyerSessionID</span><span class="p">:</span> <span class="n">Long</span><span class="p">):</span> <span class="n">ListenableFuture</span><span class="p">&lt;</span><span class="n">SignedTransaction</span><span class="p">&gt;</span> <span class="p">{</span>
<span class="k">val</span> <span class="py">seller</span> <span class="p">=</span> <span class="n">Seller</span><span class="p">(</span><span class="n">otherSide</span><span class="p">,</span> <span class="n">timestampingAuthority</span><span class="p">,</span> <span class="n">assetToSell</span><span class="p">,</span> <span class="n">price</span><span class="p">,</span> <span class="n">myKeyPair</span><span class="p">,</span> <span class="n">buyerSessionID</span><span class="p">)</span>
<span class="n">smm</span><span class="p">.</span><span class="n">add</span><span class="p">(</span><span class="s">&quot;$TRADE_TOPIC.seller&quot;</span><span class="p">,</span> <span class="n">seller</span><span class="p">)</span>
<span class="k">return</span> <span class="n">seller</span><span class="p">.</span><span class="n">resultFuture</span>
<span class="p">}</span>
<span class="k">fun</span> <span class="nf">runBuyer</span><span class="p">(</span><span class="n">smm</span><span class="p">:</span> <span class="n">StateMachineManager</span><span class="p">,</span> <span class="n">timestampingAuthority</span><span class="p">:</span> <span class="n">LegallyIdentifiableNode</span><span class="p">,</span>
<span class="n">otherSide</span><span class="p">:</span> <span class="n">SingleMessageRecipient</span><span class="p">,</span> <span class="n">acceptablePrice</span><span class="p">:</span> <span class="n">Amount</span><span class="p">,</span> <span class="n">typeToBuy</span><span class="p">:</span> <span class="n">Class</span><span class="p">&lt;</span><span class="k">out</span> <span class="n">OwnableState</span><span class="p">&gt;,</span>
2016-02-25 12:29:28 +00:00
<span class="n">sessionID</span><span class="p">:</span> <span class="n">Long</span><span class="p">):</span> <span class="n">ListenableFuture</span><span class="p">&lt;</span><span class="n">SignedTransaction</span><span class="p">&gt;</span> <span class="p">{</span>
<span class="k">val</span> <span class="py">buyer</span> <span class="p">=</span> <span class="n">Buyer</span><span class="p">(</span><span class="n">otherSide</span><span class="p">,</span> <span class="n">timestampingAuthority</span><span class="p">.</span><span class="n">identity</span><span class="p">,</span> <span class="n">acceptablePrice</span><span class="p">,</span> <span class="n">typeToBuy</span><span class="p">,</span> <span class="n">sessionID</span><span class="p">)</span>
<span class="n">smm</span><span class="p">.</span><span class="n">add</span><span class="p">(</span><span class="s">&quot;$TRADE_TOPIC.buyer&quot;</span><span class="p">,</span> <span class="n">buyer</span><span class="p">)</span>
<span class="k">return</span> <span class="n">buyer</span><span class="p">.</span><span class="n">resultFuture</span>
<span class="p">}</span>
2016-02-25 12:29:28 +00:00
<span class="c1">// This object is serialised to the network and is the first protocol message the seller sends to the buyer.</span>
<span class="k">class</span> <span class="nc">SellerTradeInfo</span><span class="p">(</span>
<span class="k">val</span> <span class="py">assetForSale</span><span class="p">:</span> <span class="n">StateAndRef</span><span class="p">&lt;</span><span class="n">OwnableState</span><span class="p">&gt;,</span>
<span class="k">val</span> <span class="py">price</span><span class="p">:</span> <span class="n">Amount</span><span class="p">,</span>
<span class="k">val</span> <span class="py">sellerOwnerKey</span><span class="p">:</span> <span class="n">PublicKey</span><span class="p">,</span>
<span class="k">val</span> <span class="py">sessionID</span><span class="p">:</span> <span class="n">Long</span>
<span class="p">)</span>
<span class="k">class</span> <span class="nc">SignaturesFromSeller</span><span class="p">(</span><span class="k">val</span> <span class="py">timestampAuthoritySig</span><span class="p">:</span> <span class="n">DigitalSignature</span><span class="p">.</span><span class="n">WithKey</span><span class="p">,</span> <span class="k">val</span> <span class="py">sellerSig</span><span class="p">:</span> <span class="n">DigitalSignature</span><span class="p">.</span><span class="n">WithKey</span><span class="p">)</span>
<span class="k">class</span> <span class="nc">Seller</span><span class="p">(</span><span class="k">val</span> <span class="py">otherSide</span><span class="p">:</span> <span class="n">SingleMessageRecipient</span><span class="p">,</span>
<span class="k">val</span> <span class="py">timestampingAuthority</span><span class="p">:</span> <span class="n">LegallyIdentifiableNode</span><span class="p">,</span>
<span class="k">val</span> <span class="py">assetToSell</span><span class="p">:</span> <span class="n">StateAndRef</span><span class="p">&lt;</span><span class="n">OwnableState</span><span class="p">&gt;,</span>
<span class="k">val</span> <span class="py">price</span><span class="p">:</span> <span class="n">Amount</span><span class="p">,</span>
<span class="k">val</span> <span class="py">myKeyPair</span><span class="p">:</span> <span class="n">KeyPair</span><span class="p">,</span>
2016-02-25 12:29:28 +00:00
<span class="k">val</span> <span class="py">buyerSessionID</span><span class="p">:</span> <span class="n">Long</span><span class="p">)</span> <span class="p">:</span> <span class="n">ProtocolLogic</span><span class="p">&lt;</span><span class="n">SignedTransaction</span><span class="p">&gt;()</span> <span class="p">{</span>
<span class="n">@Suspendable</span>
2016-02-25 12:29:28 +00:00
<span class="k">override</span> <span class="k">fun</span> <span class="nf">call</span><span class="p">():</span> <span class="n">SignedTransaction</span> <span class="p">{</span>
<span class="n">TODO</span><span class="p">()</span>
<span class="p">}</span>
<span class="p">}</span>
2016-01-27 15:01:52 +00:00
<span class="k">class</span> <span class="nc">UnacceptablePriceException</span><span class="p">(</span><span class="k">val</span> <span class="py">givenPrice</span><span class="p">:</span> <span class="n">Amount</span><span class="p">)</span> <span class="p">:</span> <span class="n">Exception</span><span class="p">()</span>
<span class="k">class</span> <span class="nc">AssetMismatchException</span><span class="p">(</span><span class="k">val</span> <span class="py">expectedTypeName</span><span class="p">:</span> <span class="n">String</span><span class="p">,</span> <span class="k">val</span> <span class="py">typeName</span><span class="p">:</span> <span class="n">String</span><span class="p">)</span> <span class="p">:</span> <span class="n">Exception</span><span class="p">()</span> <span class="p">{</span>
<span class="k">override</span> <span class="k">fun</span> <span class="nf">toString</span><span class="p">()</span> <span class="p">=</span> <span class="s">&quot;The submitted asset didn&#39;t match the expected type: $expectedTypeName vs $typeName&quot;</span>
<span class="p">}</span>
<span class="k">class</span> <span class="nc">Buyer</span><span class="p">(</span><span class="k">val</span> <span class="py">otherSide</span><span class="p">:</span> <span class="n">SingleMessageRecipient</span><span class="p">,</span>
<span class="k">val</span> <span class="py">timestampingAuthority</span><span class="p">:</span> <span class="n">Party</span><span class="p">,</span>
<span class="k">val</span> <span class="py">acceptablePrice</span><span class="p">:</span> <span class="n">Amount</span><span class="p">,</span>
<span class="k">val</span> <span class="py">typeToBuy</span><span class="p">:</span> <span class="n">Class</span><span class="p">&lt;</span><span class="k">out</span> <span class="n">OwnableState</span><span class="p">&gt;,</span>
2016-02-25 12:29:28 +00:00
<span class="k">val</span> <span class="py">sessionID</span><span class="p">:</span> <span class="n">Long</span><span class="p">)</span> <span class="p">:</span> <span class="n">ProtocolLogic</span><span class="p">&lt;</span><span class="n">SignedTransaction</span><span class="p">&gt;()</span> <span class="p">{</span>
<span class="n">@Suspendable</span>
2016-02-25 12:29:28 +00:00
<span class="k">override</span> <span class="k">fun</span> <span class="nf">call</span><span class="p">():</span> <span class="n">SignedTransaction</span> <span class="p">{</span>
<span class="n">TODO</span><span class="p">()</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="p">}</span>
2015-12-14 17:22:34 +00:00
</pre></div>
</div>
</div>
<p>Let&#8217;s unpack what this code does:</p>
<ul class="simple">
<li>It defines a several classes nested inside the main <code class="docutils literal"><span class="pre">TwoPartyTradeProtocol</span></code> singleton, and a couple of methods, one
2016-02-25 12:29:28 +00:00
to run the buyer side of the protocol and one to run the seller side. Some of the classes are simply protocol messages.</li>
<li>It defines the &#8220;trade topic&#8221;, which is just a string that namespaces this protocol. The prefix &#8220;platform.&#8221; is reserved
by the DLG, but you can define your own protocols using standard Java-style reverse DNS notation.</li>
<li>The <code class="docutils literal"><span class="pre">runBuyer</span></code> and <code class="docutils literal"><span class="pre">runSeller</span></code> methods take a number of parameters that specialise the protocol for this run,
use them to construct a <code class="docutils literal"><span class="pre">Buyer</span></code> or <code class="docutils literal"><span class="pre">Seller</span></code> object respectively, and then add the new instances to the
<code class="docutils literal"><span class="pre">StateMachineManager</span></code>. The purpose of this class is described below. The <code class="docutils literal"><span class="pre">smm.add</span></code> method takes a logger name as
the first parameter, this is just a standard JDK logging identifier string, and the instance to add.</li>
</ul>
<p>Going through the data needed to become a seller, we have:</p>
<ul class="simple">
<li><code class="docutils literal"><span class="pre">timestampingAuthority:</span> <span class="pre">LegallyIdentifiableNode</span></code> - a reference to a node on the P2P network that acts as a trusted
2016-04-13 09:29:54 +00:00
timestamper. The use of timestamping is described in <a class="reference internal" href="data-model.html"><span class="doc">Data model</span></a>.</li>
<li><code class="docutils literal"><span class="pre">otherSide:</span> <span class="pre">SingleMessageRecipient</span></code> - the network address of the node with which you are trading.</li>
<li><code class="docutils literal"><span class="pre">assetToSell:</span> <span class="pre">StateAndRef&lt;OwnableState&gt;</span></code> - a pointer to the ledger entry that represents the thing being sold.</li>
<li><code class="docutils literal"><span class="pre">price:</span> <span class="pre">Amount</span></code> - the agreed on price that the asset is being sold for.</li>
<li><code class="docutils literal"><span class="pre">myKeyPair:</span> <span class="pre">KeyPair</span></code> - the key pair that controls the asset being sold. It will be used to sign the transaction.</li>
<li><code class="docutils literal"><span class="pre">buyerSessionID:</span> <span class="pre">Long</span></code> - a unique number that identifies this trade to the buyer. It is expected that the buyer
knows that the trade is going to take place and has sent you such a number already. (This field may go away in a future
iteration of the framework)</li>
2015-12-14 17:22:34 +00:00
</ul>
2015-12-15 12:16:20 +00:00
<div class="admonition note">
<p class="first admonition-title">Note</p>
<p class="last">Session IDs keep different traffic streams separated, so for security they must be large and random enough
to be unguessable. 63 bits is good enough.</p>
2015-12-15 12:16:20 +00:00
</div>
<p>And for the buyer:</p>
<ul class="simple">
<li><code class="docutils literal"><span class="pre">acceptablePrice:</span> <span class="pre">Amount</span></code> - the price that was agreed upon out of band. If the seller specifies a price less than
or equal to this, then the trade will go ahead.</li>
<li><code class="docutils literal"><span class="pre">typeToBuy:</span> <span class="pre">Class&lt;out</span> <span class="pre">OwnableState&gt;</span></code> - the type of state that is being purchased. This is used to check that the
sell side of the protocol isn&#8217;t trying to sell us the wrong thing, whether by accident or on purpose.</li>
<li><code class="docutils literal"><span class="pre">sessionID:</span> <span class="pre">Long</span></code> - the session ID that was handed to the seller in order to start the protocol.</li>
</ul>
<p>The run methods return a <code class="docutils literal"><span class="pre">ListenableFuture</span></code> that will complete when the protocol has finished.</p>
2015-12-14 17:22:34 +00:00
<p>Alright, so using this protocol shouldn&#8217;t be too hard: in the simplest case we can just pass in the details of the trade
to either runBuyer or runSeller, depending on who we are, and then call <code class="docutils literal"><span class="pre">.get()</span></code> on resulting object to
block the calling thread until the protocol has finished. Or we could register a callback on the returned future that
will be invoked when it&#8217;s done, where we could e.g. update a user interface.</p>
2016-02-25 12:29:28 +00:00
<p>Finally, we define a couple of exceptions, and two classes that will be used as a protocol message called
<code class="docutils literal"><span class="pre">SellerTradeInfo</span></code> and <code class="docutils literal"><span class="pre">SignaturesFromSeller</span></code>.</p>
</div>
<div class="section" id="suspendable-methods">
<h2>Suspendable methods<a class="headerlink" href="#suspendable-methods" title="Permalink to this headline"></a></h2>
<p>The <code class="docutils literal"><span class="pre">call</span></code> method of the buyer/seller classes is marked with the <code class="docutils literal"><span class="pre">&#64;Suspendable</span></code> annotation. What does this mean?</p>
<p>As mentioned above, our protocol framework will at points suspend the code and serialise it to disk. For this to work,
any methods on the call stack must have been pre-marked as <code class="docutils literal"><span class="pre">&#64;Suspendable</span></code> so the bytecode rewriter knows to modify
the underlying code to support this new feature. A protocol is suspended when calling either <code class="docutils literal"><span class="pre">receive</span></code>, <code class="docutils literal"><span class="pre">send</span></code> or
<code class="docutils literal"><span class="pre">sendAndReceive</span></code> which we will learn more about below. For now, just be aware that when one of these methods is
invoked, all methods on the stack must have been marked. If you forget, then in the unit test environment you will
get a useful error message telling you which methods you didn&#8217;t mark. The fix is simple enough: just add the annotation
and try again.</p>
<div class="admonition note">
<p class="first admonition-title">Note</p>
<p class="last">A future version of Java is likely to remove this pre-marking requirement completely.</p>
</div>
2015-12-14 17:22:34 +00:00
</div>
<div class="section" id="the-state-machine-manager">
<h2>The state machine manager<a class="headerlink" href="#the-state-machine-manager" title="Permalink to this headline"></a></h2>
<p>The SMM is a class responsible for taking care of all running protocols in a node. It knows how to register handlers
with a <code class="docutils literal"><span class="pre">MessagingService</span></code> and iterate the right state machine when messages arrive. It provides the
2015-12-14 17:22:34 +00:00
send/receive/sendAndReceive calls that let the code request network interaction and it will store a serialised copy of
each state machine before it&#8217;s suspended to wait for the network.</p>
<p>To get a <code class="docutils literal"><span class="pre">StateMachineManager</span></code>, you currently have to build one by passing in a <code class="docutils literal"><span class="pre">ServiceHub</span></code> and a thread or thread
pool which it can use. This will change in future so don&#8217;t worry about the details of this too much: just check the
unit tests to see how it&#8217;s done.</p>
</div>
<div class="section" id="implementing-the-seller">
<h2>Implementing the seller<a class="headerlink" href="#implementing-the-seller" title="Permalink to this headline"></a></h2>
<p>Let&#8217;s implement the <code class="docutils literal"><span class="pre">Seller.call</span></code> method. This will be invoked by the platform when the protocol is started by the
<code class="docutils literal"><span class="pre">StateMachineManager</span></code>.</p>
2015-12-14 17:22:34 +00:00
<div class="codeset container">
2016-04-13 09:29:54 +00:00
<div class="highlight-kotlin"><div class="highlight"><pre><span></span><span class="k">val</span> <span class="py">partialTX</span><span class="p">:</span> <span class="n">SignedTransaction</span> <span class="p">=</span> <span class="n">receiveAndCheckProposedTransaction</span><span class="p">()</span>
2015-12-14 17:22:34 +00:00
2016-02-25 12:29:28 +00:00
<span class="c1">// These two steps could be done in parallel, in theory. Our framework doesn&#39;t support that yet though.</span>
<span class="k">val</span> <span class="py">ourSignature</span> <span class="p">=</span> <span class="n">signWithOurKey</span><span class="p">(</span><span class="n">partialTX</span><span class="p">)</span>
<span class="k">val</span> <span class="py">tsaSig</span> <span class="p">=</span> <span class="n">subProtocol</span><span class="p">(</span><span class="n">TimestampingProtocol</span><span class="p">(</span><span class="n">timestampingAuthority</span><span class="p">,</span> <span class="n">partialTX</span><span class="p">.</span><span class="n">txBits</span><span class="p">))</span>
2015-12-14 17:22:34 +00:00
2016-02-25 12:29:28 +00:00
<span class="k">val</span> <span class="py">stx</span><span class="p">:</span> <span class="n">SignedTransaction</span> <span class="p">=</span> <span class="n">sendSignatures</span><span class="p">(</span><span class="n">partialTX</span><span class="p">,</span> <span class="n">ourSignature</span><span class="p">,</span> <span class="n">tsaSig</span><span class="p">)</span>
<span class="k">return</span> <span class="n">stx</span>
</pre></div>
</div>
</div>
<p>Here we see the outline of the procedure. We receive a proposed trade transaction from the buyer and check that it&#8217;s
valid. Then we sign with our own key, request a timestamping authority to assert with another signature that the
timestamp in the transaction (if any) is valid, and finally we send back both our signature and the TSA&#8217;s signature.
Finally, we hand back to the code that invoked the protocol the finished transaction in a couple of different forms.</p>
<div class="admonition note">
<p class="first admonition-title">Note</p>
<p class="last"><code class="docutils literal"><span class="pre">ProtocolLogic</span></code> classes can be composed together. Here, we see the use of the <code class="docutils literal"><span class="pre">subProtocol</span></code> method, which
is given an instance of <code class="docutils literal"><span class="pre">TimestampingProtocol</span></code>. This protocol will run to completion and yield a result, almost
as if it&#8217;s a regular method call. In fact, under the hood, all the <code class="docutils literal"><span class="pre">subProtocol</span></code> method does is pass the current
fiber object into the newly created object and then run <code class="docutils literal"><span class="pre">call()</span></code> on it ... so it basically _is_ just a method call.
This is where we can see the benefits of using continuations/fibers as a programming model.</p>
</div>
<p>Let&#8217;s fill out the <code class="docutils literal"><span class="pre">receiveAndCheckProposedTransaction()</span></code> method.</p>
<div class="codeset container">
2016-04-13 09:29:54 +00:00
<div class="highlight-kotlin"><div class="highlight"><pre><span></span><span class="n">@Suspendable</span>
2016-02-25 12:29:28 +00:00
<span class="k">open</span> <span class="k">fun</span> <span class="nf">receiveAndCheckProposedTransaction</span><span class="p">():</span> <span class="n">SignedTransaction</span> <span class="p">{</span>
<span class="k">val</span> <span class="py">sessionID</span> <span class="p">=</span> <span class="n">random63BitValue</span><span class="p">()</span>
<span class="c1">// Make the first message we&#39;ll send to kick off the protocol.</span>
<span class="k">val</span> <span class="py">hello</span> <span class="p">=</span> <span class="n">SellerTradeInfo</span><span class="p">(</span><span class="n">assetToSell</span><span class="p">,</span> <span class="n">price</span><span class="p">,</span> <span class="n">myKeyPair</span><span class="p">.</span><span class="k">public</span><span class="p">,</span> <span class="n">sessionID</span><span class="p">)</span>
<span class="k">val</span> <span class="py">maybeSTX</span> <span class="p">=</span> <span class="n">sendAndReceive</span><span class="p">&lt;</span><span class="n">SignedTransaction</span><span class="p">&gt;(</span><span class="n">TRADE_TOPIC</span><span class="p">,</span> <span class="n">otherSide</span><span class="p">,</span> <span class="n">buyerSessionID</span><span class="p">,</span> <span class="n">sessionID</span><span class="p">,</span> <span class="n">hello</span><span class="p">)</span>
<span class="n">maybeSTX</span><span class="p">.</span><span class="n">validate</span> <span class="p">{</span>
<span class="c1">// Check that the tx proposed by the buyer is valid.</span>
<span class="k">val</span> <span class="py">missingSigs</span> <span class="p">=</span> <span class="n">it</span><span class="p">.</span><span class="n">verify</span><span class="p">(</span><span class="n">throwIfSignaturesAreMissing</span> <span class="p">=</span> <span class="k">false</span><span class="p">)</span>
<span class="k">if</span> <span class="p">(</span><span class="n">missingSigs</span> <span class="p">!=</span> <span class="n">setOf</span><span class="p">(</span><span class="n">myKeyPair</span><span class="p">.</span><span class="k">public</span><span class="p">,</span> <span class="n">timestampingAuthority</span><span class="p">.</span><span class="n">identity</span><span class="p">.</span><span class="n">owningKey</span><span class="p">))</span>
<span class="k">throw</span> <span class="n">SignatureException</span><span class="p">(</span><span class="s">&quot;The set of missing signatures is not as expected: $missingSigs&quot;</span><span class="p">)</span>
<span class="k">val</span> <span class="py">wtx</span><span class="p">:</span> <span class="n">WireTransaction</span> <span class="p">=</span> <span class="n">it</span><span class="p">.</span><span class="n">tx</span>
<span class="n">logger</span><span class="p">.</span><span class="n">trace</span> <span class="p">{</span> <span class="s">&quot;Received partially signed transaction: ${it.id}&quot;</span> <span class="p">}</span>
<span class="n">checkDependencies</span><span class="p">(</span><span class="n">it</span><span class="p">)</span>
<span class="c1">// This verifies that the transaction is contract-valid, even though it is missing signatures.</span>
<span class="n">serviceHub</span><span class="p">.</span><span class="n">verifyTransaction</span><span class="p">(</span><span class="n">wtx</span><span class="p">.</span><span class="n">toLedgerTransaction</span><span class="p">(</span><span class="n">serviceHub</span><span class="p">.</span><span class="n">identityService</span><span class="p">))</span>
<span class="k">if</span> <span class="p">(</span><span class="n">wtx</span><span class="p">.</span><span class="n">outputs</span><span class="p">.</span><span class="n">sumCashBy</span><span class="p">(</span><span class="n">myKeyPair</span><span class="p">.</span><span class="k">public</span><span class="p">)</span> <span class="p">!=</span> <span class="n">price</span><span class="p">)</span>
<span class="k">throw</span> <span class="n">IllegalArgumentException</span><span class="p">(</span><span class="s">&quot;Transaction is not sending us the right amounnt of cash&quot;</span><span class="p">)</span>
<span class="c1">// There are all sorts of funny games a malicious secondary might play here, we should fix them:</span>
<span class="c1">//</span>
<span class="c1">// - This tx may attempt to send some assets we aren&#39;t intending to sell to the secondary, if</span>
<span class="c1">// we&#39;re reusing keys! So don&#39;t reuse keys!</span>
<span class="c1">// - This tx may include output states that impose odd conditions on the movement of the cash,</span>
<span class="c1">// once we implement state pairing.</span>
<span class="c1">//</span>
<span class="c1">// but the goal of this code is not to be fully secure (yet), but rather, just to find good ways to</span>
<span class="c1">// express protocol state machines on top of the messaging layer.</span>
<span class="k">return</span> <span class="n">it</span>
<span class="p">}</span>
<span class="p">}</span>
2015-12-14 17:22:34 +00:00
</pre></div>
</div>
</div>
<p>That&#8217;s pretty straightforward. We generate a session ID to identify what&#8217;s happening on the seller side, fill out
2015-12-14 17:22:34 +00:00
the initial protocol message, and then call <code class="docutils literal"><span class="pre">sendAndReceive</span></code>. This function takes a few arguments:</p>
<ul class="simple">
<li>The topic string that ensures the message is routed to the right bit of code in the other side&#8217;s node.</li>
<li>The session IDs that ensure the messages don&#8217;t get mixed up with other simultaneous trades.</li>
<li>The thing to send. It&#8217;ll be serialised and sent automatically.</li>
<li>Finally a type argument, which is the kind of object we&#8217;re expecting to receive from the other side.</li>
2015-12-14 17:22:34 +00:00
</ul>
2016-02-25 12:29:28 +00:00
<p>Once <code class="docutils literal"><span class="pre">sendAndReceive</span></code> is called, the call method will be suspended into a continuation. When it gets back we&#8217;ll do a log
2015-12-14 17:22:34 +00:00
message. The buyer is supposed to send us a transaction with all the right inputs/outputs/commands in return, with their
cash put into the transaction and their signature on it authorising the movement of the cash.</p>
<div class="admonition note">
<p class="first admonition-title">Note</p>
<p>There are a couple of rules you need to bear in mind when writing a class that will be used as a continuation.
2015-12-14 17:22:34 +00:00
The first is that anything on the stack when the function is suspended will be stored into the heap and kept alive by
the garbage collector. So try to avoid keeping enormous data structures alive unless you really have to.</p>
<p class="last">The second is that as well as being kept on the heap, objects reachable from the stack will be serialised. The state
2015-12-14 17:22:34 +00:00
of the function call may be resurrected much later! Kryo doesn&#8217;t require objects be marked as serialisable, but even so,
doing things like creating threads from inside these calls would be a bad idea. They should only contain business
logic.</p>
</div>
2016-02-25 12:29:28 +00:00
<p>You get back a simple wrapper class, <code class="docutils literal"><span class="pre">UntrustworthyData&lt;SignedTransaction&gt;</span></code>, which is just a marker class that reminds
us that the data came from a potentially malicious external source and may have been tampered with or be unexpected in
other ways. It doesn&#8217;t add any functionality, but acts as a reminder to &#8220;scrub&#8221; the data before use. Here, our scrubbing
simply involves checking the signatures on it. Then we go ahead and check all the dependencies of this partial
transaction for validity. Here&#8217;s the code to do that:</p>
2015-12-14 17:22:34 +00:00
<div class="codeset container">
2016-04-13 09:29:54 +00:00
<div class="highlight-kotlin"><div class="highlight"><pre><span></span><span class="n">@Suspendable</span>
2016-02-25 12:29:28 +00:00
<span class="k">private</span> <span class="k">fun</span> <span class="nf">checkDependencies</span><span class="p">(</span><span class="n">stx</span><span class="p">:</span> <span class="n">SignedTransaction</span><span class="p">)</span> <span class="p">{</span>
<span class="c1">// Download and check all the transactions that this transaction depends on, but do not check this</span>
<span class="c1">// transaction itself.</span>
<span class="k">val</span> <span class="py">dependencyTxIDs</span> <span class="p">=</span> <span class="n">stx</span><span class="p">.</span><span class="n">tx</span><span class="p">.</span><span class="n">inputs</span><span class="p">.</span><span class="n">map</span> <span class="p">{</span> <span class="n">it</span><span class="p">.</span><span class="n">txhash</span> <span class="p">}.</span><span class="n">toSet</span><span class="p">()</span>
<span class="n">subProtocol</span><span class="p">(</span><span class="n">ResolveTransactionsProtocol</span><span class="p">(</span><span class="n">dependencyTxIDs</span><span class="p">,</span> <span class="n">otherSide</span><span class="p">))</span>
2015-12-14 17:22:34 +00:00
<span class="p">}</span>
2016-02-25 12:29:28 +00:00
</pre></div>
</div>
</div>
<p>This is simple enough: we mark the method as <code class="docutils literal"><span class="pre">&#64;Suspendable</span></code> because we&#8217;re going to invoke a sub-protocol, extract the
IDs of the transactions the proposed transaction depends on, and then uses a protocol provided by the system to download
and check them all. This protocol does a breadth-first search over the dependency graph, bottoming out at issuance
transactions that don&#8217;t have any inputs themselves. Once the node has audited the transaction history, all the dependencies
are committed to the node&#8217;s local database so they won&#8217;t be checked again next time.</p>
<div class="admonition note">
<p class="first admonition-title">Note</p>
<p class="last">Transaction dependency resolution assumes that the peer you got the transaction from has all of the
dependencies itself. It must do, otherwise it could not have convinced itself that the dependencies were themselves
valid. It&#8217;s important to realise that requesting only the transactions we require is a privacy leak, because if
we don&#8217;t download a transaction from the peer, they know we must have already seen it before. Fixing this privacy
leak will come later.</p>
</div>
<p>After the dependencies, we check the proposed trading transaction for validity by running the contracts for that as
well (but having handled the fact that some signatures are missing ourselves).</p>
<p>Here&#8217;s the rest of the code:</p>
<div class="codeset container">
2016-04-13 09:29:54 +00:00
<div class="highlight-kotlin"><div class="highlight"><pre><span></span><span class="k">open</span> <span class="k">fun</span> <span class="nf">signWithOurKey</span><span class="p">(</span><span class="n">partialTX</span><span class="p">:</span> <span class="n">SignedTransaction</span><span class="p">)</span> <span class="p">=</span> <span class="n">myKeyPair</span><span class="p">.</span><span class="n">signWithECDSA</span><span class="p">(</span><span class="n">partialTX</span><span class="p">.</span><span class="n">txBits</span><span class="p">)</span>
2015-12-14 17:22:34 +00:00
2016-02-25 12:29:28 +00:00
<span class="n">@Suspendable</span>
<span class="k">open</span> <span class="k">fun</span> <span class="nf">sendSignatures</span><span class="p">(</span><span class="n">partialTX</span><span class="p">:</span> <span class="n">SignedTransaction</span><span class="p">,</span> <span class="n">ourSignature</span><span class="p">:</span> <span class="n">DigitalSignature</span><span class="p">.</span><span class="n">WithKey</span><span class="p">,</span>
<span class="n">tsaSig</span><span class="p">:</span> <span class="n">DigitalSignature</span><span class="p">.</span><span class="n">LegallyIdentifiable</span><span class="p">):</span> <span class="n">SignedTransaction</span> <span class="p">{</span>
<span class="k">val</span> <span class="py">fullySigned</span> <span class="p">=</span> <span class="n">partialTX</span> <span class="p">+</span> <span class="n">tsaSig</span> <span class="p">+</span> <span class="n">ourSignature</span>
2015-12-14 17:22:34 +00:00
2016-02-25 12:29:28 +00:00
<span class="n">logger</span><span class="p">.</span><span class="n">trace</span> <span class="p">{</span> <span class="s">&quot;Built finished transaction, sending back to secondary!&quot;</span> <span class="p">}</span>
2015-12-14 17:22:34 +00:00
2016-02-25 12:29:28 +00:00
<span class="n">send</span><span class="p">(</span><span class="n">TRADE_TOPIC</span><span class="p">,</span> <span class="n">otherSide</span><span class="p">,</span> <span class="n">buyerSessionID</span><span class="p">,</span> <span class="n">SignaturesFromSeller</span><span class="p">(</span><span class="n">tsaSig</span><span class="p">,</span> <span class="n">ourSignature</span><span class="p">))</span>
<span class="k">return</span> <span class="n">fullySigned</span>
<span class="p">}</span>
2015-12-14 17:22:34 +00:00
</pre></div>
</div>
</div>
2016-02-25 12:29:28 +00:00
<p>It&#8217;s should be all pretty straightforward: here, <code class="docutils literal"><span class="pre">txBits</span></code> is the raw byte array representing the transaction.</p>
<p>In <code class="docutils literal"><span class="pre">sendSignatures</span></code>, we take the two signatures we calculated, then add them to the partial transaction we were sent.
We provide an overload for the + operator so signatures can be added to a SignedTransaction easily. Finally, we wrap the
two signatures in a simple wrapper message class and send it back. The send won&#8217;t block waiting for an acknowledgement,
but the underlying message queue software will retry delivery if the other side has gone away temporarily.</p>
2015-12-14 17:22:34 +00:00
<div class="admonition warning">
<p class="first admonition-title">Warning</p>
<p class="last">This code is <strong>not secure</strong>. Other than not checking for all possible invalid constructions, if the
seller stops before sending the finalised transaction to the buyer, the seller is left with a valid transaction
but the buyer isn&#8217;t, so they can&#8217;t spend the asset they just purchased! This sort of thing will be fixed in a
future version of the code.</p>
</div>
</div>
<div class="section" id="implementing-the-buyer">
<h2>Implementing the buyer<a class="headerlink" href="#implementing-the-buyer" title="Permalink to this headline"></a></h2>
<p>OK, let&#8217;s do the same for the buyer side:</p>
<div class="codeset container">
2016-04-13 09:29:54 +00:00
<div class="highlight-kotlin"><div class="highlight"><pre><span></span>@Suspendable
2016-02-25 12:29:28 +00:00
override fun call(): SignedTransaction {
val tradeRequest = receiveAndValidateTradeRequest()
val (ptx, cashSigningPubKeys) = assembleSharedTX(tradeRequest)
val stx = signWithOurKeys(cashSigningPubKeys, ptx)
val signatures = swapSignaturesWithSeller(stx, tradeRequest.sessionID)
logger.trace { &quot;Got signatures from seller, verifying ... &quot;}
val fullySigned = stx + signatures.timestampAuthoritySig + signatures.sellerSig
fullySigned.verify()
logger.trace { &quot;Fully signed transaction was valid. Trade complete! :-)&quot; }
return fullySigned
}
@Suspendable
open fun receiveAndValidateTradeRequest(): SellerTradeInfo {
// Wait for a trade request to come in on our pre-provided session ID.
2016-02-25 12:29:28 +00:00
val maybeTradeRequest = receive&lt;SellerTradeInfo&gt;(TRADE_TOPIC, sessionID)
maybeTradeRequest.validate {
// What is the seller trying to sell us?
val asset = it.assetForSale.state
val assetTypeName = asset.javaClass.name
logger.trace { &quot;Got trade request for a $assetTypeName: ${it.assetForSale}&quot; }
// Check the start message for acceptability.
check(it.sessionID &gt; 0)
if (it.price &gt; acceptablePrice)
throw UnacceptablePriceException(it.price)
if (!typeToBuy.isInstance(asset))
throw AssetMismatchException(typeToBuy.name, assetTypeName)
// Check the transaction that contains the state which is being resolved.
// We only have a hash here, so if we don&#39;t know it already, we have to ask for it.
subProtocol(ResolveTransactionsProtocol(setOf(it.assetForSale.ref.txhash), otherSide))
return it
}
}
2016-02-25 12:29:28 +00:00
@Suspendable
open fun swapSignaturesWithSeller(stx: SignedTransaction, theirSessionID: Long): SignaturesFromSeller {
logger.trace { &quot;Sending partially signed transaction to seller&quot; }
2016-02-25 12:29:28 +00:00
// TODO: Protect against the seller terminating here and leaving us in the lurch without the final tx.
2016-02-25 12:29:28 +00:00
return sendAndReceive(TRADE_TOPIC, otherSide, theirSessionID, sessionID, stx, SignaturesFromSeller::class.java).validate { it }
}
2016-02-25 12:29:28 +00:00
open fun signWithOurKeys(cashSigningPubKeys: List&lt;PublicKey&gt;, ptx: TransactionBuilder): SignedTransaction {
// Now sign the transaction with whatever keys we need to move the cash.
for (k in cashSigningPubKeys) {
val priv = serviceHub.keyManagementService.toPrivate(k)
ptx.signWith(KeyPair(k, priv))
}
return ptx.toSignedTransaction(checkSufficientSignatures = false)
}
open fun assembleSharedTX(tradeRequest: SellerTradeInfo): Pair&lt;TransactionBuilder, List&lt;PublicKey&gt;&gt; {
val ptx = TransactionBuilder()
2016-02-25 12:29:28 +00:00
// Add input and output states for the movement of cash, by using the Cash contract to generate the states.
val wallet = serviceHub.walletService.currentWallet
val cashStates = wallet.statesOfType&lt;Cash.State&gt;()
2016-02-25 12:29:28 +00:00
val cashSigningPubKeys = Cash().generateSpend(ptx, tradeRequest.price, tradeRequest.sellerOwnerKey, cashStates)
// Add inputs/outputs/a command for the movement of the asset.
ptx.addInputState(tradeRequest.assetForSale.ref)
2016-02-25 12:29:28 +00:00
// Just pick some new public key for now. This won&#39;t be linked with our identity in any way, which is what
// we want for privacy reasons: the key is here ONLY to manage and control ownership, it is not intended to
// reveal who the owner actually is. The key management service is expected to derive a unique key from some
// initial seed in order to provide privacy protection.
val freshKey = serviceHub.keyManagementService.freshKey()
val (command, state) = tradeRequest.assetForSale.state.withNewOwner(freshKey.public)
ptx.addOutputState(state)
2016-02-25 12:29:28 +00:00
ptx.addCommand(command, tradeRequest.assetForSale.state.owner)
2016-02-25 12:29:28 +00:00
// And add a request for timestamping: it may be that none of the contracts need this! But it can&#39;t hurt
// to have one.
ptx.setTime(Instant.now(), timestampingAuthority, 30.seconds)
return Pair(ptx, cashSigningPubKeys)
2015-12-14 17:22:34 +00:00
}
</pre></div>
</div>
</div>
<p>This code is longer but still fairly straightforward. Here are some things to pay attention to:</p>
2015-12-14 17:22:34 +00:00
<ol class="arabic simple">
<li>We do some sanity checking on the received message to ensure we&#8217;re being offered what we expected to be offered.</li>
2016-02-25 12:29:28 +00:00
<li>We create a cash spend in the normal way, by using <code class="docutils literal"><span class="pre">Cash().generateSpend</span></code>. See the contracts tutorial if this isn&#8217;t
clear.</li>
2015-12-14 17:22:34 +00:00
<li>We access the <em>service hub</em> when we need it to access things that are transient and may change or be recreated
whilst a protocol is suspended, things like the wallet or the timestamping service. Remember that a protocol may
be suspended when it waits to receive a message across node or computer restarts, so objects representing a service
or data which may frequently change should be accessed &#8216;just in time&#8217;.</li>
2016-02-25 12:29:28 +00:00
<li>Finally, we send the unfinished, invalid transaction to the seller so they can sign it. They are expected to send
back to us a <code class="docutils literal"><span class="pre">SignaturesFromSeller</span></code>, which once we verify it, should be the final outcome of the trade.</li>
2015-12-14 17:22:34 +00:00
</ol>
<p>As you can see, the protocol logic is straightforward and does not contain any callbacks or network glue code, despite
the fact that it takes minimal resources and can survive node restarts.</p>
<div class="admonition warning">
<p class="first admonition-title">Warning</p>
<p class="last">When accessing things via the <code class="docutils literal"><span class="pre">serviceHub</span></code> field, avoid the temptation to stuff a reference into a local variable.
If you do this then next time your protocol waits to receive an object, the system will try and serialise all your
local variables and end up trying to serialise, e.g. the timestamping service, which doesn&#8217;t make any conceptual
sense. The <code class="docutils literal"><span class="pre">serviceHub</span></code> field is defined by the <code class="docutils literal"><span class="pre">ProtocolStateMachine</span></code> superclass and is marked transient so
this problem doesn&#8217;t occur. It&#8217;s also restored for you when a protocol state machine is restored after a node
2015-12-14 17:22:34 +00:00
restart.</p>
</div>
</div>
2016-02-25 12:29:28 +00:00
<div class="section" id="progress-tracking">
<h2>Progress tracking<a class="headerlink" href="#progress-tracking" title="Permalink to this headline"></a></h2>
<p>Not shown in the code snippets above is the usage of the <code class="docutils literal"><span class="pre">ProgressTracker</span></code> API. Progress tracking exports information
from a protocol about where it&#8217;s got up to in such a way that observers can render it in a useful manner to humans who
may need to be informed. It may be rendered via an API, in a GUI, onto a terminal window, etc.</p>
<p>A <code class="docutils literal"><span class="pre">ProgressTracker</span></code> is constructed with a series of <code class="docutils literal"><span class="pre">Step</span></code> objects, where each step is an object representing a
stage in a piece of work. It is therefore typical to use singletons that subclass <code class="docutils literal"><span class="pre">Step</span></code>, which may be defined easily
in one line when using Kotlin. Typical steps might be &#8220;Waiting for response from peer&#8221;, &#8220;Waiting for signature to be
approved&#8221;, &#8220;Downloading and verifying data&#8221; etc.</p>
<p>Each step exposes a label. By default labels are fixed, but by subclassing <code class="docutils literal"><span class="pre">RelabelableStep</span></code>
you can make a step that can update its label on the fly. That&#8217;s useful for steps that want to expose non-structured
progress information like the current file being downloaded. By defining your own step types, you can export progress
in a way that&#8217;s both human readable and machine readable.</p>
<p>Progress trackers are hierarchical. Each step can be the parent for another tracker. By altering the
<code class="docutils literal"><span class="pre">ProgressTracker.childrenFor[step]</span> <span class="pre">=</span> <span class="pre">tracker</span></code> map, a tree of steps can be created. It&#8217;s allowed to alter the hierarchy
at runtime, on the fly, and the progress renderers will adapt to that properly. This can be helpful when you don&#8217;t
fully know ahead of time what steps will be required. If you _do_ know what is required, configuring as much of the
hierarchy ahead of time is a good idea, as that will help the users see what is coming up.</p>
<p>Every tracker has not only the steps given to it at construction time, but also the singleton
<code class="docutils literal"><span class="pre">ProgressTracker.UNSTARTED</span></code> step and the <code class="docutils literal"><span class="pre">ProgressTracker.DONE</span></code> step. Once a tracker has become <code class="docutils literal"><span class="pre">DONE</span></code> its
position may not be modified again (because e.g. the UI may have been removed/cleaned up), but until that point, the
position can be set to any arbitrary set both forwards and backwards. Steps may be skipped, repeated, etc. Note that
rolling the current step backwards will delete any progress trackers that are children of the steps being reversed, on
the assumption that those subtasks will have to be repeated.</p>
<p>Trackers provide an <a class="reference external" href="http://reactivex.io/">Rx observable</a> which streams changes to the hierarchy. The top level
observable exposes all the events generated by its children as well. The changes are represented by objects indicating
whether the change is one of position (i.e. progress), structure (i.e. new subtasks being added/removed) or some other
aspect of rendering (i.e. a step has changed in some way and is requesting a re-render).</p>
<p>The protocol framework is somewhat integrated with this API. Each <code class="docutils literal"><span class="pre">ProtocolLogic</span></code> may optionally provide a tracker by
overriding the <code class="docutils literal"><span class="pre">protocolTracker</span></code> property (<code class="docutils literal"><span class="pre">getProtocolTracker</span></code> method in Java). If the
<code class="docutils literal"><span class="pre">ProtocolLogic.subProtocol</span></code> method is used, then the tracker of the sub-protocol will be made a child of the current
step in the parent protocol automatically, if the parent is using tracking in the first place. The framework will also
automatically set the current step to <code class="docutils literal"><span class="pre">DONE</span></code> for you, when the protocol is finished.</p>
<p>Because a protocol may sometimes wish to configure the children in its progress hierarchy _before_ the sub-protocol
is constructed, for sub-protocols that always follow the same outline regardless of their parameters it&#8217;s conventional
to define a companion object/static method (for Kotlin/Java respectively) that constructs a tracker, and then allow
the sub-protocol to have the tracker it will use be passed in as a parameter. This allows all trackers to be built
and linked ahead of time.</p>
<p>In future, the progress tracking framework will become a vital part of how exceptions, errors, and other faults are
surfaced to human operators for investigation and resolution.</p>
</div>
2015-12-14 17:22:34 +00:00
</div>
</div>
</div>
<footer>
<div class="rst-footer-buttons" role="navigation" aria-label="footer navigation">
2016-03-15 16:13:01 +00:00
<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>
2015-12-14 17:22:34 +00:00
2016-07-12 16:52:52 +00:00
<a href="tutorial-test-dsl.html" class="btn btn-neutral" title="Writing a contract test" accesskey="p"><span class="fa fa-arrow-circle-left"></span> Previous</a>
2015-12-14 17:22:34 +00:00
</div>
<hr/>
<div role="contentinfo">
<p>
2016-05-09 16:13:23 +00:00
&copy; Copyright 2016, Distributed Ledger Group, LLC.
2015-12-14 17:22:34 +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:'./',
2016-02-25 12:29:28 +00:00
VERSION:'latest',
2015-12-14 17:22:34 +00:00
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>