mirror of
https://github.com/corda/corda.git
synced 2024-12-26 16:11:12 +00:00
967 lines
97 KiB
HTML
967 lines
97 KiB
HTML
|
|
|
|
<!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>Writing a contract — 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="Writing a contract using clauses" href="tutorial-contract-clauses.html"/>
|
|
<link rel="prev" title="Where to start" href="where-to-start.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>
|
|
|
|
</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>
|
|
<li class="toctree-l1"><a class="reference internal" href="inthebox.html">What’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>
|
|
<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>
|
|
<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="creating-a-cordapp.html">Creating a Cordapp</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="node-administration.html">Node administration</a></li>
|
|
<li class="toctree-l1"><a class="reference internal" href="corda-configuration-files.html">The Corda Configuration File</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="where-to-start.html">Where to start</a></li>
|
|
<li class="toctree-l1 current"><a class="current reference internal" href="#">Writing a contract</a><ul>
|
|
<li class="toctree-l2"><a class="reference internal" href="#where-to-put-your-code">Where to put your code</a></li>
|
|
<li class="toctree-l2"><a class="reference internal" href="#starting-the-commercial-paper-class">Starting the commercial paper class</a></li>
|
|
<li class="toctree-l2"><a class="reference internal" href="#states">States</a></li>
|
|
<li class="toctree-l2"><a class="reference internal" href="#commands">Commands</a></li>
|
|
<li class="toctree-l2"><a class="reference internal" href="#the-verify-function">The verify function</a></li>
|
|
<li class="toctree-l2"><a class="reference internal" href="#using-state-groups">Using state groups</a></li>
|
|
<li class="toctree-l2"><a class="reference internal" href="#checking-the-requirements">Checking the requirements</a></li>
|
|
<li class="toctree-l2"><a class="reference internal" href="#how-to-test-your-contract">How to test your contract</a></li>
|
|
<li class="toctree-l2"><a class="reference internal" href="#adding-a-generation-api-to-your-contract">Adding a generation API to your contract</a></li>
|
|
<li class="toctree-l2"><a class="reference internal" href="#how-multi-party-transactions-are-constructed-and-transmitted">How multi-party transactions are constructed and transmitted</a></li>
|
|
<li class="toctree-l2"><a class="reference internal" href="#non-asset-oriented-smart-contracts">Non-asset-oriented smart contracts</a></li>
|
|
<li class="toctree-l2"><a class="reference internal" href="#making-things-happen-at-a-particular-time">Making things happen at a particular time</a></li>
|
|
<li class="toctree-l2"><a class="reference internal" href="#encumbrances">Encumbrances</a></li>
|
|
<li class="toctree-l2"><a class="reference internal" href="#clauses">Clauses</a></li>
|
|
</ul>
|
|
</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-clientrpc-api.html">Client RPC API</a></li>
|
|
<li class="toctree-l1"><a class="reference internal" href="protocol-state-machines.html">Protocol state machines</a></li>
|
|
<li class="toctree-l1"><a class="reference internal" href="oracles.html">Writing oracle services</a></li>
|
|
<li class="toctree-l1"><a class="reference internal" href="tutorial-attachments.html">Using attachments</a></li>
|
|
<li class="toctree-l1"><a class="reference internal" href="event-scheduling.html">Event scheduling</a></li>
|
|
<li class="toctree-l1"><a class="reference internal" href="secure-coding-guidelines.html">Secure coding guidelines</a></li>
|
|
</ul>
|
|
<p class="caption"><span class="caption-text">Contracts</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">Node API</span></p>
|
|
<ul>
|
|
<li class="toctree-l1"><a class="reference internal" href="clientrpc.html">Client RPC</a></li>
|
|
</ul>
|
|
<p class="caption"><span class="caption-text">Appendix</span></p>
|
|
<ul>
|
|
<li class="toctree-l1"><a class="reference internal" href="release-process.html">Release process</a></li>
|
|
<li class="toctree-l1"><a class="reference internal" href="release-process.html#steps-to-cut-a-release">Steps to cut a release</a></li>
|
|
<li class="toctree-l1"><a class="reference internal" href="release-notes.html">Release notes</a></li>
|
|
<li class="toctree-l1"><a class="reference internal" href="network-simulator.html">Network Simulator</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>
|
|
</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> »</li>
|
|
|
|
<li>Writing a contract</li>
|
|
<li class="wy-breadcrumbs-aside">
|
|
|
|
|
|
<a href="_sources/tutorial-contract.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="writing-a-contract">
|
|
<h1>Writing a contract<a class="headerlink" href="#writing-a-contract" title="Permalink to this headline">¶</a></h1>
|
|
<p>This tutorial will take you through how the commercial paper contract works. This uses a simple contract structure of
|
|
everything being in one contract class, while most actual contracts in Corda are broken into clauses (which we’ll
|
|
discuss in the next tutorial). Clauses help reduce tedious boilerplate, but it’s worth understanding how a
|
|
contract is built without them before starting.</p>
|
|
<p>You can see the full Kotlin version of this contract in the code as <code class="docutils literal"><span class="pre">CommercialPaperLegacy</span></code>. The code in this
|
|
tutorial is available in both Kotlin and Java. You can quickly switch between them to get a feeling for how
|
|
Kotlin syntax works.</p>
|
|
<div class="section" id="where-to-put-your-code">
|
|
<h2>Where to put your code<a class="headerlink" href="#where-to-put-your-code" title="Permalink to this headline">¶</a></h2>
|
|
<p>A CorDapp is a collection of contracts, state definitions, protocols and other ways to extend the server. To create
|
|
one you would just create a Java-style project as normal, with your choice of build system (Maven, Gradle, etc).
|
|
Then add a dependency on <code class="docutils literal"><span class="pre">com.r3corda:core:0.X</span></code> where X is the milestone number you are depending on. The core
|
|
module defines the base classes used in this tutorial.</p>
|
|
</div>
|
|
<div class="section" id="starting-the-commercial-paper-class">
|
|
<h2>Starting the commercial paper class<a class="headerlink" href="#starting-the-commercial-paper-class" title="Permalink to this headline">¶</a></h2>
|
|
<p>A smart contract is a class that implements the <code class="docutils literal"><span class="pre">Contract</span></code> interface. This can be either implemented directly, or
|
|
by subclassing an abstract contract such as <code class="docutils literal"><span class="pre">OnLedgerAsset</span></code>.</p>
|
|
<div class="codeset container">
|
|
<div class="highlight-kotlin"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">CommercialPaper</span> <span class="p">:</span> <span class="n">Contract</span> <span class="p">{</span>
|
|
<span class="k">override</span> <span class="k">val</span> <span class="py">legalContractReference</span><span class="p">:</span> <span class="n">SecureHash</span> <span class="p">=</span> <span class="n">SecureHash</span><span class="p">.</span><span class="n">sha256</span><span class="p">(</span><span class="s">"https://en.wikipedia.org/wiki/Commercial_paper"</span><span class="p">);</span>
|
|
|
|
<span class="k">override</span> <span class="k">fun</span> <span class="nf">verify</span><span class="p">(</span><span class="n">tx</span><span class="p">:</span> <span class="n">TransactionForVerification</span><span class="p">)</span> <span class="p">{</span>
|
|
<span class="n">TODO</span><span class="p">()</span>
|
|
<span class="p">}</span>
|
|
<span class="p">}</span>
|
|
</pre></div>
|
|
</div>
|
|
<div class="highlight-java"><div class="highlight"><pre><span></span><span class="kd">public</span> <span class="kd">class</span> <span class="nc">CommercialPaper</span> <span class="kd">implements</span> <span class="n">Contract</span> <span class="o">{</span>
|
|
<span class="nd">@Override</span>
|
|
<span class="kd">public</span> <span class="n">SecureHash</span> <span class="nf">getLegalContractReference</span><span class="o">()</span> <span class="o">{</span>
|
|
<span class="k">return</span> <span class="n">SecureHash</span><span class="o">.</span><span class="na">Companion</span><span class="o">.</span><span class="na">sha256</span><span class="o">(</span><span class="s">"https://en.wikipedia.org/wiki/Commercial_paper"</span><span class="o">);</span>
|
|
<span class="o">}</span>
|
|
|
|
<span class="nd">@Override</span>
|
|
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">verify</span><span class="o">(</span><span class="n">TransactionForVerification</span> <span class="n">tx</span><span class="o">)</span> <span class="o">{</span>
|
|
<span class="k">throw</span> <span class="k">new</span> <span class="n">UnsupportedOperationException</span><span class="o">();</span>
|
|
<span class="o">}</span>
|
|
<span class="o">}</span>
|
|
</pre></div>
|
|
</div>
|
|
</div>
|
|
<p>Every contract must have at least a <code class="docutils literal"><span class="pre">getLegalContractReference()</span></code> and a <code class="docutils literal"><span class="pre">verify()</span></code> method. In Kotlin we express
|
|
a getter without a setter as an immutable property (val). The <em>legal contract reference</em> is supposed to be a hash
|
|
of a document that describes the legal contract and may take precedence over the code, in case of a dispute.</p>
|
|
<div class="admonition note">
|
|
<p class="first admonition-title">Note</p>
|
|
<p class="last">The way legal contract prose is bound to a smart contract implementation will change in future.</p>
|
|
</div>
|
|
<p>The verify method returns nothing. This is intentional: the function either completes correctly, or throws an exception,
|
|
in which case the transaction is rejected.</p>
|
|
<p>So far, so simple. Now we need to define the commercial paper <em>state</em>, which represents the fact of ownership of a
|
|
piece of issued paper.</p>
|
|
</div>
|
|
<div class="section" id="states">
|
|
<h2>States<a class="headerlink" href="#states" title="Permalink to this headline">¶</a></h2>
|
|
<p>A state is a class that stores data that is checked by the contract.</p>
|
|
<div class="codeset container">
|
|
<div class="highlight-kotlin"><div class="highlight"><pre><span></span><span class="k">data</span> <span class="k">class</span> <span class="nc">State</span><span class="p">(</span>
|
|
<span class="k">val</span> <span class="py">issuance</span><span class="p">:</span> <span class="n">PartyAndReference</span><span class="p">,</span>
|
|
<span class="k">override</span> <span class="k">val</span> <span class="py">owner</span><span class="p">:</span> <span class="n">PublicKey</span><span class="p">,</span>
|
|
<span class="k">val</span> <span class="py">faceValue</span><span class="p">:</span> <span class="n">Amount</span><span class="p"><</span><span class="n">Issued</span><span class="p"><</span><span class="n">Currency</span><span class="p">>>,</span>
|
|
<span class="k">val</span> <span class="py">maturityDate</span><span class="p">:</span> <span class="n">Instant</span>
|
|
<span class="p">)</span> <span class="p">:</span> <span class="n">OwnableState</span> <span class="p">{</span>
|
|
<span class="k">override</span> <span class="k">val</span> <span class="py">contract</span> <span class="p">=</span> <span class="n">CommercialPaper</span><span class="p">()</span>
|
|
<span class="k">override</span> <span class="k">val</span> <span class="py">participants</span> <span class="p">=</span> <span class="n">listOf</span><span class="p">(</span><span class="n">owner</span><span class="p">)</span>
|
|
|
|
<span class="k">fun</span> <span class="nf">withoutOwner</span><span class="p">()</span> <span class="p">=</span> <span class="n">copy</span><span class="p">(</span><span class="n">owner</span> <span class="p">=</span> <span class="n">NullPublicKey</span><span class="p">)</span>
|
|
<span class="k">override</span> <span class="k">fun</span> <span class="nf">withNewOwner</span><span class="p">(</span><span class="n">newOwner</span><span class="p">:</span> <span class="n">PublicKey</span><span class="p">)</span> <span class="p">=</span> <span class="n">Pair</span><span class="p">(</span><span class="n">Commands</span><span class="p">.</span><span class="n">Move</span><span class="p">(),</span> <span class="n">copy</span><span class="p">(</span><span class="n">owner</span> <span class="p">=</span> <span class="n">newOwner</span><span class="p">))</span>
|
|
<span class="p">}</span>
|
|
</pre></div>
|
|
</div>
|
|
<div class="highlight-java"><div class="highlight"><pre><span></span><span class="kd">public</span> <span class="kd">static</span> <span class="kd">class</span> <span class="nc">State</span> <span class="kd">implements</span> <span class="n">OwnableState</span> <span class="o">{</span>
|
|
<span class="kd">private</span> <span class="n">PartyAndReference</span> <span class="n">issuance</span><span class="o">;</span>
|
|
<span class="kd">private</span> <span class="n">PublicKey</span> <span class="n">owner</span><span class="o">;</span>
|
|
<span class="kd">private</span> <span class="n">Amount</span><span class="o"><</span><span class="n">Issued</span><span class="o"><</span><span class="n">Currency</span><span class="o">>></span> <span class="n">faceValue</span><span class="o">;</span>
|
|
<span class="kd">private</span> <span class="n">Instant</span> <span class="n">maturityDate</span><span class="o">;</span>
|
|
|
|
<span class="kd">public</span> <span class="nf">State</span><span class="o">()</span> <span class="o">{</span>
|
|
<span class="o">}</span> <span class="c1">// For serialization</span>
|
|
|
|
<span class="kd">public</span> <span class="nf">State</span><span class="o">(</span><span class="n">PartyAndReference</span> <span class="n">issuance</span><span class="o">,</span> <span class="n">PublicKey</span> <span class="n">owner</span><span class="o">,</span> <span class="n">Amount</span><span class="o"><</span><span class="n">Issued</span><span class="o"><</span><span class="n">Currency</span><span class="o">>></span> <span class="n">faceValue</span><span class="o">,</span>
|
|
<span class="n">Instant</span> <span class="n">maturityDate</span><span class="o">)</span> <span class="o">{</span>
|
|
<span class="k">this</span><span class="o">.</span><span class="na">issuance</span> <span class="o">=</span> <span class="n">issuance</span><span class="o">;</span>
|
|
<span class="k">this</span><span class="o">.</span><span class="na">owner</span> <span class="o">=</span> <span class="n">owner</span><span class="o">;</span>
|
|
<span class="k">this</span><span class="o">.</span><span class="na">faceValue</span> <span class="o">=</span> <span class="n">faceValue</span><span class="o">;</span>
|
|
<span class="k">this</span><span class="o">.</span><span class="na">maturityDate</span> <span class="o">=</span> <span class="n">maturityDate</span><span class="o">;</span>
|
|
<span class="o">}</span>
|
|
|
|
<span class="kd">public</span> <span class="n">State</span> <span class="nf">copy</span><span class="o">()</span> <span class="o">{</span>
|
|
<span class="k">return</span> <span class="k">new</span> <span class="n">State</span><span class="o">(</span><span class="k">this</span><span class="o">.</span><span class="na">issuance</span><span class="o">,</span> <span class="k">this</span><span class="o">.</span><span class="na">owner</span><span class="o">,</span> <span class="k">this</span><span class="o">.</span><span class="na">faceValue</span><span class="o">,</span> <span class="k">this</span><span class="o">.</span><span class="na">maturityDate</span><span class="o">);</span>
|
|
<span class="o">}</span>
|
|
|
|
<span class="nd">@NotNull</span>
|
|
<span class="nd">@Override</span>
|
|
<span class="kd">public</span> <span class="n">Pair</span><span class="o"><</span><span class="n">CommandData</span><span class="o">,</span> <span class="n">OwnableState</span><span class="o">></span> <span class="nf">withNewOwner</span><span class="o">(</span><span class="nd">@NotNull</span> <span class="n">PublicKey</span> <span class="n">newOwner</span><span class="o">)</span> <span class="o">{</span>
|
|
<span class="k">return</span> <span class="k">new</span> <span class="n">Pair</span><span class="o"><>(</span><span class="k">new</span> <span class="n">Commands</span><span class="o">.</span><span class="na">Move</span><span class="o">(),</span> <span class="k">new</span> <span class="n">State</span><span class="o">(</span><span class="k">this</span><span class="o">.</span><span class="na">issuance</span><span class="o">,</span> <span class="n">newOwner</span><span class="o">,</span> <span class="k">this</span><span class="o">.</span><span class="na">faceValue</span><span class="o">,</span> <span class="k">this</span><span class="o">.</span><span class="na">maturityDate</span><span class="o">));</span>
|
|
<span class="o">}</span>
|
|
|
|
<span class="kd">public</span> <span class="n">PartyAndReference</span> <span class="nf">getIssuance</span><span class="o">()</span> <span class="o">{</span>
|
|
<span class="k">return</span> <span class="n">issuance</span><span class="o">;</span>
|
|
<span class="o">}</span>
|
|
|
|
<span class="kd">public</span> <span class="n">PublicKey</span> <span class="nf">getOwner</span><span class="o">()</span> <span class="o">{</span>
|
|
<span class="k">return</span> <span class="n">owner</span><span class="o">;</span>
|
|
<span class="o">}</span>
|
|
|
|
<span class="kd">public</span> <span class="n">Amount</span><span class="o"><</span><span class="n">Issued</span><span class="o"><</span><span class="n">Currency</span><span class="o">>></span> <span class="nf">getFaceValue</span><span class="o">()</span> <span class="o">{</span>
|
|
<span class="k">return</span> <span class="n">faceValue</span><span class="o">;</span>
|
|
<span class="o">}</span>
|
|
|
|
<span class="kd">public</span> <span class="n">Instant</span> <span class="nf">getMaturityDate</span><span class="o">()</span> <span class="o">{</span>
|
|
<span class="k">return</span> <span class="n">maturityDate</span><span class="o">;</span>
|
|
<span class="o">}</span>
|
|
|
|
<span class="nd">@NotNull</span>
|
|
<span class="nd">@Override</span>
|
|
<span class="kd">public</span> <span class="n">Contract</span> <span class="nf">getContract</span><span class="o">()</span> <span class="o">{</span>
|
|
<span class="k">return</span> <span class="k">new</span> <span class="n">JavaCommercialPaper</span><span class="o">();</span>
|
|
<span class="o">}</span>
|
|
|
|
<span class="nd">@Override</span>
|
|
<span class="kd">public</span> <span class="kt">boolean</span> <span class="nf">equals</span><span class="o">(</span><span class="n">Object</span> <span class="n">o</span><span class="o">)</span> <span class="o">{</span>
|
|
<span class="k">if</span> <span class="o">(</span><span class="k">this</span> <span class="o">==</span> <span class="n">o</span><span class="o">)</span> <span class="k">return</span> <span class="kc">true</span><span class="o">;</span>
|
|
<span class="k">if</span> <span class="o">(</span><span class="n">o</span> <span class="o">==</span> <span class="kc">null</span> <span class="o">||</span> <span class="n">getClass</span><span class="o">()</span> <span class="o">!=</span> <span class="n">o</span><span class="o">.</span><span class="na">getClass</span><span class="o">())</span> <span class="k">return</span> <span class="kc">false</span><span class="o">;</span>
|
|
|
|
<span class="n">State</span> <span class="n">state</span> <span class="o">=</span> <span class="o">(</span><span class="n">State</span><span class="o">)</span> <span class="n">o</span><span class="o">;</span>
|
|
|
|
<span class="k">if</span> <span class="o">(</span><span class="n">issuance</span> <span class="o">!=</span> <span class="kc">null</span> <span class="o">?</span> <span class="o">!</span><span class="n">issuance</span><span class="o">.</span><span class="na">equals</span><span class="o">(</span><span class="n">state</span><span class="o">.</span><span class="na">issuance</span><span class="o">)</span> <span class="o">:</span> <span class="n">state</span><span class="o">.</span><span class="na">issuance</span> <span class="o">!=</span> <span class="kc">null</span><span class="o">)</span> <span class="k">return</span> <span class="kc">false</span><span class="o">;</span>
|
|
<span class="k">if</span> <span class="o">(</span><span class="n">owner</span> <span class="o">!=</span> <span class="kc">null</span> <span class="o">?</span> <span class="o">!</span><span class="n">owner</span><span class="o">.</span><span class="na">equals</span><span class="o">(</span><span class="n">state</span><span class="o">.</span><span class="na">owner</span><span class="o">)</span> <span class="o">:</span> <span class="n">state</span><span class="o">.</span><span class="na">owner</span> <span class="o">!=</span> <span class="kc">null</span><span class="o">)</span> <span class="k">return</span> <span class="kc">false</span><span class="o">;</span>
|
|
<span class="k">if</span> <span class="o">(</span><span class="n">faceValue</span> <span class="o">!=</span> <span class="kc">null</span> <span class="o">?</span> <span class="o">!</span><span class="n">faceValue</span><span class="o">.</span><span class="na">equals</span><span class="o">(</span><span class="n">state</span><span class="o">.</span><span class="na">faceValue</span><span class="o">)</span> <span class="o">:</span> <span class="n">state</span><span class="o">.</span><span class="na">faceValue</span> <span class="o">!=</span> <span class="kc">null</span><span class="o">)</span> <span class="k">return</span> <span class="kc">false</span><span class="o">;</span>
|
|
<span class="k">return</span> <span class="o">!(</span><span class="n">maturityDate</span> <span class="o">!=</span> <span class="kc">null</span> <span class="o">?</span> <span class="o">!</span><span class="n">maturityDate</span><span class="o">.</span><span class="na">equals</span><span class="o">(</span><span class="n">state</span><span class="o">.</span><span class="na">maturityDate</span><span class="o">)</span> <span class="o">:</span> <span class="n">state</span><span class="o">.</span><span class="na">maturityDate</span> <span class="o">!=</span> <span class="kc">null</span><span class="o">);</span>
|
|
<span class="o">}</span>
|
|
|
|
<span class="nd">@Override</span>
|
|
<span class="kd">public</span> <span class="kt">int</span> <span class="nf">hashCode</span><span class="o">()</span> <span class="o">{</span>
|
|
<span class="kt">int</span> <span class="n">result</span> <span class="o">=</span> <span class="n">issuance</span> <span class="o">!=</span> <span class="kc">null</span> <span class="o">?</span> <span class="n">issuance</span><span class="o">.</span><span class="na">hashCode</span><span class="o">()</span> <span class="o">:</span> <span class="mi">0</span><span class="o">;</span>
|
|
<span class="n">result</span> <span class="o">=</span> <span class="mi">31</span> <span class="o">*</span> <span class="n">result</span> <span class="o">+</span> <span class="o">(</span><span class="n">owner</span> <span class="o">!=</span> <span class="kc">null</span> <span class="o">?</span> <span class="n">owner</span><span class="o">.</span><span class="na">hashCode</span><span class="o">()</span> <span class="o">:</span> <span class="mi">0</span><span class="o">);</span>
|
|
<span class="n">result</span> <span class="o">=</span> <span class="mi">31</span> <span class="o">*</span> <span class="n">result</span> <span class="o">+</span> <span class="o">(</span><span class="n">faceValue</span> <span class="o">!=</span> <span class="kc">null</span> <span class="o">?</span> <span class="n">faceValue</span><span class="o">.</span><span class="na">hashCode</span><span class="o">()</span> <span class="o">:</span> <span class="mi">0</span><span class="o">);</span>
|
|
<span class="n">result</span> <span class="o">=</span> <span class="mi">31</span> <span class="o">*</span> <span class="n">result</span> <span class="o">+</span> <span class="o">(</span><span class="n">maturityDate</span> <span class="o">!=</span> <span class="kc">null</span> <span class="o">?</span> <span class="n">maturityDate</span><span class="o">.</span><span class="na">hashCode</span><span class="o">()</span> <span class="o">:</span> <span class="mi">0</span><span class="o">);</span>
|
|
<span class="k">return</span> <span class="n">result</span><span class="o">;</span>
|
|
<span class="o">}</span>
|
|
|
|
<span class="nd">@NotNull</span>
|
|
<span class="nd">@Override</span>
|
|
<span class="kd">public</span> <span class="n">List</span><span class="o"><</span><span class="n">PublicKey</span><span class="o">></span> <span class="nf">getParticipants</span><span class="o">()</span> <span class="o">{</span>
|
|
<span class="k">return</span> <span class="n">ImmutableList</span><span class="o">.</span><span class="na">of</span><span class="o">(</span><span class="k">this</span><span class="o">.</span><span class="na">owner</span><span class="o">);</span>
|
|
<span class="o">}</span>
|
|
<span class="o">}</span>
|
|
</pre></div>
|
|
</div>
|
|
</div>
|
|
<p>We define a class that implements the <code class="docutils literal"><span class="pre">ContractState</span></code> interface.</p>
|
|
<p>The <code class="docutils literal"><span class="pre">ContractState</span></code> interface requires us to provide a <code class="docutils literal"><span class="pre">getContract</span></code> method that returns an instance of the
|
|
contract class itself. In future, this will change to support dynamic loading of contracts with versioning
|
|
and signing constraints, but for now this is how it’s written.</p>
|
|
<p>We have four fields in our state:</p>
|
|
<ul class="simple">
|
|
<li><code class="docutils literal"><span class="pre">issuance</span></code>, a reference to a specific piece of commercial paper issued by some party.</li>
|
|
<li><code class="docutils literal"><span class="pre">owner</span></code>, the public key of the current owner. This is the same concept as seen in Bitcoin: the public key has no
|
|
attached identity and is expected to be one-time-use for privacy reasons. However, unlike in Bitcoin, we model
|
|
ownership at the level of individual states rather than as a platform-level concept as we envisage many
|
|
(possibly most) contracts on the platform will not represent “owner/issuer” relationships, but “party/party”
|
|
relationships such as a derivative contract.</li>
|
|
<li><code class="docutils literal"><span class="pre">faceValue</span></code>, an <code class="docutils literal"><span class="pre">Amount<Issued<Currency>></span></code>, which wraps an integer number of pennies and a currency that is
|
|
specific to some issuer (e.g. a regular bank, a central bank, etc). You can read more about this very common
|
|
type in <a class="reference internal" href="transaction-data-types.html"><span class="doc">Data types</span></a>.</li>
|
|
<li><code class="docutils literal"><span class="pre">maturityDate</span></code>, an <a class="reference external" href="https://docs.oracle.com/javase/8/docs/api/java/time/Instant.html">Instant</a>, which is a type
|
|
from the Java 8 standard time library. It defines a point on the timeline.</li>
|
|
</ul>
|
|
<p>States are immutable, and thus the class is defined as immutable as well. The <code class="docutils literal"><span class="pre">data</span></code> modifier in the Kotlin version
|
|
causes the compiler to generate the equals/hashCode/toString methods automatically, along with a copy method that can
|
|
be used to create variants of the original object. Data classes are similar to case classes in Scala, if you are
|
|
familiar with that language. The <code class="docutils literal"><span class="pre">withoutOwner</span></code> method uses the auto-generated copy method to return a version of
|
|
the state with the owner public key blanked out: this will prove useful later.</p>
|
|
<p>The Java code compiles to almost identical bytecode as the Kotlin version, but as you can see, is much more verbose.</p>
|
|
</div>
|
|
<div class="section" id="commands">
|
|
<h2>Commands<a class="headerlink" href="#commands" title="Permalink to this headline">¶</a></h2>
|
|
<p>The logic for a contract may vary depending on what stage of a lifecycle it is automating. So it can be useful to
|
|
pass additional data into the contract code that isn’t represented by the states which exist permanently in the ledger.</p>
|
|
<p>For this purpose we have commands. Often they don’t need to contain any data at all, they just need to exist. A command
|
|
is a piece of data associated with some <em>signatures</em>. By the time the contract runs the signatures have already been
|
|
checked, so from the contract code’s perspective, a command is simply a data structure with a list of attached
|
|
public keys. Each key had a signature proving that the corresponding private key was used to sign. Because of this
|
|
approach contracts never actually interact or work with digital signatures directly.</p>
|
|
<p>Let’s define a few commands now:</p>
|
|
<div class="codeset container">
|
|
<div class="highlight-kotlin"><div class="highlight"><pre><span></span><span class="k">interface</span> <span class="nc">Commands</span> <span class="p">:</span> <span class="n">CommandData</span> <span class="p">{</span>
|
|
<span class="k">class</span> <span class="nc">Move</span> <span class="p">:</span> <span class="n">TypeOnlyCommandData</span><span class="p">(),</span> <span class="n">Commands</span>
|
|
<span class="k">class</span> <span class="nc">Redeem</span> <span class="p">:</span> <span class="n">TypeOnlyCommandData</span><span class="p">(),</span> <span class="n">Commands</span>
|
|
<span class="k">class</span> <span class="nc">Issue</span> <span class="p">:</span> <span class="n">TypeOnlyCommandData</span><span class="p">(),</span> <span class="n">Commands</span>
|
|
<span class="p">}</span>
|
|
</pre></div>
|
|
</div>
|
|
<div class="highlight-java"><div class="highlight"><pre><span></span><span class="kd">public</span> <span class="kd">static</span> <span class="kd">class</span> <span class="nc">Commands</span> <span class="kd">implements</span> <span class="n">core</span><span class="o">.</span><span class="na">contract</span><span class="o">.</span><span class="na">Command</span> <span class="o">{</span>
|
|
<span class="kd">public</span> <span class="kd">static</span> <span class="kd">class</span> <span class="nc">Move</span> <span class="kd">extends</span> <span class="n">Commands</span> <span class="o">{</span>
|
|
<span class="nd">@Override</span>
|
|
<span class="kd">public</span> <span class="kt">boolean</span> <span class="nf">equals</span><span class="o">(</span><span class="n">Object</span> <span class="n">obj</span><span class="o">)</span> <span class="o">{</span>
|
|
<span class="k">return</span> <span class="n">obj</span> <span class="k">instanceof</span> <span class="n">Move</span><span class="o">;</span>
|
|
<span class="o">}</span>
|
|
<span class="o">}</span>
|
|
|
|
<span class="kd">public</span> <span class="kd">static</span> <span class="kd">class</span> <span class="nc">Redeem</span> <span class="kd">extends</span> <span class="n">Commands</span> <span class="o">{</span>
|
|
<span class="nd">@Override</span>
|
|
<span class="kd">public</span> <span class="kt">boolean</span> <span class="nf">equals</span><span class="o">(</span><span class="n">Object</span> <span class="n">obj</span><span class="o">)</span> <span class="o">{</span>
|
|
<span class="k">return</span> <span class="n">obj</span> <span class="k">instanceof</span> <span class="n">Redeem</span><span class="o">;</span>
|
|
<span class="o">}</span>
|
|
<span class="o">}</span>
|
|
|
|
<span class="kd">public</span> <span class="kd">static</span> <span class="kd">class</span> <span class="nc">Issue</span> <span class="kd">extends</span> <span class="n">Commands</span> <span class="o">{</span>
|
|
<span class="nd">@Override</span>
|
|
<span class="kd">public</span> <span class="kt">boolean</span> <span class="nf">equals</span><span class="o">(</span><span class="n">Object</span> <span class="n">obj</span><span class="o">)</span> <span class="o">{</span>
|
|
<span class="k">return</span> <span class="n">obj</span> <span class="k">instanceof</span> <span class="n">Issue</span><span class="o">;</span>
|
|
<span class="o">}</span>
|
|
<span class="o">}</span>
|
|
<span class="o">}</span>
|
|
</pre></div>
|
|
</div>
|
|
</div>
|
|
<p>We define a simple grouping interface or static class, this gives us a type that all our commands have in common,
|
|
then we go ahead and create three commands: <code class="docutils literal"><span class="pre">Move</span></code>, <code class="docutils literal"><span class="pre">Redeem</span></code>, <code class="docutils literal"><span class="pre">Issue</span></code>. <code class="docutils literal"><span class="pre">TypeOnlyCommandData</span></code> is a helpful utility
|
|
for the case when there’s no data inside the command; only the existence matters. It defines equals and hashCode
|
|
such that any instances always compare equal and hash to the same value.</p>
|
|
</div>
|
|
<div class="section" id="the-verify-function">
|
|
<h2>The verify function<a class="headerlink" href="#the-verify-function" title="Permalink to this headline">¶</a></h2>
|
|
<p>The heart of a smart contract is the code that verifies a set of state transitions (a <em>transaction</em>). The function is
|
|
simple: it’s given a class representing the transaction, and if the function returns then the transaction is considered
|
|
acceptable. If it throws an exception, the transaction is rejected.</p>
|
|
<p>Each transaction can have multiple input and output states of different types. The set of contracts to run is decided
|
|
by taking the code references inside each state. Each contract is run only once. As an example, a contract that includes
|
|
2 cash states and 1 commercial paper state as input, and has as output 1 cash state and 1 commercial paper state, will
|
|
run two contracts one time each: Cash and CommercialPaper.</p>
|
|
<div class="codeset container">
|
|
<div class="highlight-kotlin"><div class="highlight"><pre><span></span><span class="k">override</span> <span class="k">fun</span> <span class="nf">verify</span><span class="p">(</span><span class="n">tx</span><span class="p">:</span> <span class="n">TransactionForContract</span><span class="p">)</span> <span class="p">{</span>
|
|
<span class="c1">// Group by everything except owner: any modification to the CP at all is considered changing it fundamentally.</span>
|
|
<span class="k">val</span> <span class="py">groups</span> <span class="p">=</span> <span class="n">tx</span><span class="p">.</span><span class="n">groupStates</span><span class="p">(</span><span class="n">State</span><span class="o">::</span><span class="n">withoutOwner</span><span class="p">)</span>
|
|
|
|
<span class="c1">// There are two possible things that can be done with this CP. The first is trading it. The second is redeeming</span>
|
|
<span class="c1">// it for cash on or after the maturity date.</span>
|
|
<span class="k">val</span> <span class="py">command</span> <span class="p">=</span> <span class="n">tx</span><span class="p">.</span><span class="n">commands</span><span class="p">.</span><span class="n">requireSingleCommand</span><span class="p"><</span><span class="n">CommercialPaper</span><span class="p">.</span><span class="n">Commands</span><span class="p">>()</span>
|
|
</pre></div>
|
|
</div>
|
|
<div class="highlight-java"><div class="highlight"><pre><span></span><span class="nd">@Override</span>
|
|
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">verify</span><span class="o">(</span><span class="n">TransactionForContract</span> <span class="n">tx</span><span class="o">)</span> <span class="o">{</span>
|
|
<span class="n">List</span><span class="o"><</span><span class="n">InOutGroup</span><span class="o"><</span><span class="n">State</span><span class="o">,</span> <span class="n">State</span><span class="o">>></span> <span class="n">groups</span> <span class="o">=</span> <span class="n">tx</span><span class="o">.</span><span class="na">groupStates</span><span class="o">(</span><span class="n">State</span><span class="o">.</span><span class="na">class</span><span class="o">,</span> <span class="n">State</span><span class="o">::</span><span class="n">withoutOwner</span><span class="o">);</span>
|
|
<span class="n">AuthenticatedObject</span><span class="o"><</span><span class="n">Command</span><span class="o">></span> <span class="n">cmd</span> <span class="o">=</span> <span class="n">requireSingleCommand</span><span class="o">(</span><span class="n">tx</span><span class="o">.</span><span class="na">getCommands</span><span class="o">(),</span> <span class="n">Commands</span><span class="o">.</span><span class="na">class</span><span class="o">);</span>
|
|
</pre></div>
|
|
</div>
|
|
</div>
|
|
<p>We start by using the <code class="docutils literal"><span class="pre">groupStates</span></code> method, which takes a type and a function. State grouping is a way of ensuring
|
|
your contract can handle multiple unrelated states of the same type in the same transaction, which is needed for
|
|
splitting/merging of assets, atomic swaps and so on. More on this next.</p>
|
|
<p>The second line does what the code suggests: it searches for a command object that inherits from the
|
|
<code class="docutils literal"><span class="pre">CommercialPaper.Commands</span></code> supertype, and either returns it, or throws an exception if there’s zero or more than one
|
|
such command.</p>
|
|
</div>
|
|
<div class="section" id="using-state-groups">
|
|
<h2>Using state groups<a class="headerlink" href="#using-state-groups" title="Permalink to this headline">¶</a></h2>
|
|
<p>The simplest way to write a smart contract would be to say that each transaction can have a single input state and a
|
|
single output state of the kind govered by that contract. This would be easy for the developer, but would prevent many
|
|
important use cases.</p>
|
|
<p>The next easiest way to write a contract would be to iterate over each input state and expect it to have an output
|
|
state. Now you can build a single transaction that, for instance, moves two different cash states in different currencies
|
|
simultaneously. But it gets complicated when you want to issue or exit one state at the same time as moving another.</p>
|
|
<p>Things get harder still once you want to split and merge states. We say states are <em>fungible</em> if they are
|
|
treated identically to each other by the recipient, despite the fact that they aren’t quite identical. Dollar bills are
|
|
fungible because even though one may be worn/a bit dirty and another may be crisp and new, they are still both worth
|
|
exactly $1. Likewise, ten $1 bills are almost exactly equivalent to one $10 bill. On the other hand, $10 and £10 are not
|
|
fungible: if you tried to pay for something that cost £20 with $10+£10 notes your trade would not be accepted.</p>
|
|
<p>To make all this easier the contract API provides a notion of groups. A group is a set of input states and output states
|
|
that should be checked for validity together.</p>
|
|
<p>Consider the following simplified currency trade transaction:</p>
|
|
<ul class="simple">
|
|
<li><strong>Input</strong>: $12,000 owned by Alice (A)</li>
|
|
<li><strong>Input</strong>: $3,000 owned by Alice (A)</li>
|
|
<li><strong>Input</strong>: £10,000 owned by Bob (B)</li>
|
|
<li><strong>Output</strong>: £10,000 owned by Alice (B)</li>
|
|
<li><strong>Output</strong>: $15,000 owned by Bob (A)</li>
|
|
</ul>
|
|
<p>In this transaction Alice and Bob are trading $15,000 for £10,000. Alice has her money in the form of two different
|
|
inputs e.g. because she received the dollars in two payments. The input and output amounts do balance correctly, but
|
|
the cash smart contract must consider the pounds and the dollars separately because they are not fungible: they cannot
|
|
be merged together. So we have two groups: A and B.</p>
|
|
<p>The <code class="docutils literal"><span class="pre">TransactionForContract.groupStates</span></code> method handles this logic for us: firstly, it selects only states of the
|
|
given type (as the transaction may include other types of state, such as states representing bond ownership, or a
|
|
multi-sig state) and then it takes a function that maps a state to a grouping key. All states that share the same key are
|
|
grouped together. In the case of the cash example above, the grouping key would be the currency.</p>
|
|
<p>In this kind of contract we don’t want CP to be fungible: merging and splitting is (in our example) not allowed.
|
|
So we just use a copy of the state minus the owner field as the grouping key.</p>
|
|
<p>Here are some code examples:</p>
|
|
<div class="codeset container">
|
|
<div class="highlight-kotlin"><div class="highlight"><pre><span></span>// Type of groups is List<InOutGroup<State, Pair<PartyReference, Currency>>>
|
|
val groups = tx.groupStates() { it: Cash.State -> Pair(it.deposit, it.amount.currency) }
|
|
for ((inputs, outputs, key) in groups) {
|
|
// Either inputs or outputs could be empty.
|
|
val (deposit, currency) = key
|
|
|
|
...
|
|
}
|
|
</pre></div>
|
|
</div>
|
|
<div class="highlight-java"><div class="highlight"><pre><span></span><span class="n">List</span><span class="o"><</span><span class="n">InOutGroup</span><span class="o"><</span><span class="n">State</span><span class="o">,</span> <span class="n">Pair</span><span class="o"><</span><span class="n">PartyReference</span><span class="o">,</span> <span class="n">Currency</span><span class="o">>>></span> <span class="n">groups</span> <span class="o">=</span> <span class="n">tx</span><span class="o">.</span><span class="na">groupStates</span><span class="o">(</span><span class="n">Cash</span><span class="o">.</span><span class="na">State</span><span class="o">.</span><span class="na">class</span><span class="o">,</span> <span class="n">s</span> <span class="o">-></span> <span class="n">Pair</span><span class="o">(</span><span class="n">s</span><span class="o">.</span><span class="na">deposit</span><span class="o">,</span> <span class="n">s</span><span class="o">.</span><span class="na">amount</span><span class="o">.</span><span class="na">currency</span><span class="o">))</span>
|
|
<span class="k">for</span> <span class="o">(</span><span class="n">InOutGroup</span><span class="o"><</span><span class="n">State</span><span class="o">,</span> <span class="n">Pair</span><span class="o"><</span><span class="n">PartyReference</span><span class="o">,</span> <span class="n">Currency</span><span class="o">>></span> <span class="n">group</span> <span class="o">:</span> <span class="n">groups</span><span class="o">)</span> <span class="o">{</span>
|
|
<span class="n">List</span><span class="o"><</span><span class="n">State</span><span class="o">></span> <span class="n">inputs</span> <span class="o">=</span> <span class="n">group</span><span class="o">.</span><span class="na">getInputs</span><span class="o">();</span>
|
|
<span class="n">List</span><span class="o"><</span><span class="n">State</span><span class="o">></span> <span class="n">outputs</span> <span class="o">=</span> <span class="n">group</span><span class="o">.</span><span class="na">getOutputs</span><span class="o">();</span>
|
|
<span class="n">Pair</span><span class="o"><</span><span class="n">PartyReference</span><span class="o">,</span> <span class="n">Currency</span><span class="o">></span> <span class="n">key</span> <span class="o">=</span> <span class="n">group</span><span class="o">.</span><span class="na">getKey</span><span class="o">();</span>
|
|
|
|
<span class="o">...</span>
|
|
<span class="o">}</span>
|
|
</pre></div>
|
|
</div>
|
|
</div>
|
|
<p>The <code class="docutils literal"><span class="pre">groupStates</span></code> call uses the provided function to calculate a “grouping key”. All states that have the same
|
|
grouping key are placed in the same group. A grouping key can be anything that implements equals/hashCode, but it’s
|
|
always an aggregate of the fields that shouldn’t change between input and output. In the above example we picked the
|
|
fields we wanted and packed them into a <code class="docutils literal"><span class="pre">Pair</span></code>. It returns a list of <code class="docutils literal"><span class="pre">InOutGroup</span></code>, which is just a holder for the
|
|
inputs, outputs and the key that was used to define the group. In the Kotlin version we unpack these using destructuring
|
|
to get convenient access to the inputs, the outputs, the deposit data and the currency. The Java version is more
|
|
verbose, but equivalent.</p>
|
|
<p>The rules can then be applied to the inputs and outputs as if it were a single transaction. A group may have zero
|
|
inputs or zero outputs: this can occur when issuing assets onto the ledger, or removing them.</p>
|
|
<p>In this example, we do it differently and use the state class itself as the aggregator. We just
|
|
blank out fields that are allowed to change, making the grouping key be “everything that isn’t that”:</p>
|
|
<div class="codeset container">
|
|
<div class="highlight-kotlin"><div class="highlight"><pre><span></span><span class="k">val</span> <span class="py">groups</span> <span class="p">=</span> <span class="n">tx</span><span class="p">.</span><span class="n">groupStates</span><span class="p">()</span> <span class="p">{</span> <span class="n">it</span><span class="p">:</span> <span class="n">State</span> <span class="p">-></span> <span class="n">it</span><span class="p">.</span><span class="n">withoutOwner</span><span class="p">()</span> <span class="p">}</span>
|
|
</pre></div>
|
|
</div>
|
|
<div class="highlight-java"><div class="highlight"><pre><span></span><span class="n">List</span><span class="o"><</span><span class="n">InOutGroup</span><span class="o"><</span><span class="n">State</span><span class="o">,</span> <span class="n">State</span><span class="o">>></span> <span class="n">groups</span> <span class="o">=</span> <span class="n">tx</span><span class="o">.</span><span class="na">groupStates</span><span class="o">(</span><span class="n">State</span><span class="o">.</span><span class="na">class</span><span class="o">,</span> <span class="n">State</span><span class="o">::</span><span class="n">withoutOwner</span><span class="o">);</span>
|
|
</pre></div>
|
|
</div>
|
|
</div>
|
|
<p>For large states with many fields that must remain constant and only one or two that are really mutable, it’s often
|
|
easier to do things this way than to specifically name each field that must stay the same. The <code class="docutils literal"><span class="pre">withoutOwner</span></code> function
|
|
here simply returns a copy of the object but with the <code class="docutils literal"><span class="pre">owner</span></code> field set to <code class="docutils literal"><span class="pre">NullPublicKey</span></code>, which is just a public key
|
|
of all zeros. It’s invalid and useless, but that’s OK, because all we’re doing is preventing the field from mattering
|
|
in equals and hashCode.</p>
|
|
</div>
|
|
<div class="section" id="checking-the-requirements">
|
|
<h2>Checking the requirements<a class="headerlink" href="#checking-the-requirements" title="Permalink to this headline">¶</a></h2>
|
|
<p>After extracting the command and the groups, we then iterate over each group and verify it meets the required business
|
|
logic.</p>
|
|
<div class="codeset container">
|
|
<div class="highlight-kotlin"><div class="highlight"><pre><span></span><span class="k">val</span> <span class="py">timestamp</span><span class="p">:</span> <span class="n">Timestamp</span><span class="p">?</span> <span class="p">=</span> <span class="n">tx</span><span class="p">.</span><span class="n">timestamp</span>
|
|
|
|
<span class="k">for</span> <span class="p">((</span><span class="n">inputs</span><span class="p">,</span> <span class="n">outputs</span><span class="p">,</span> <span class="n">key</span><span class="p">)</span> <span class="k">in</span> <span class="n">groups</span><span class="p">)</span> <span class="p">{</span>
|
|
<span class="k">when</span> <span class="p">(</span><span class="n">command</span><span class="p">.</span><span class="n">value</span><span class="p">)</span> <span class="p">{</span>
|
|
<span class="k">is</span> <span class="n">Commands</span><span class="p">.</span><span class="n">Move</span> <span class="p">-></span> <span class="p">{</span>
|
|
<span class="k">val</span> <span class="py">input</span> <span class="p">=</span> <span class="n">inputs</span><span class="p">.</span><span class="n">single</span><span class="p">()</span>
|
|
<span class="n">requireThat</span> <span class="p">{</span>
|
|
<span class="s">"the transaction is signed by the owner of the CP"</span> <span class="k">by</span> <span class="p">(</span><span class="n">input</span><span class="p">.</span><span class="n">owner</span> <span class="k">in</span> <span class="n">command</span><span class="p">.</span><span class="n">signers</span><span class="p">)</span>
|
|
<span class="s">"the state is propagated"</span> <span class="k">by</span> <span class="p">(</span><span class="n">group</span><span class="p">.</span><span class="n">outputs</span><span class="p">.</span><span class="n">size</span> <span class="p">==</span> <span class="m">1</span><span class="p">)</span>
|
|
<span class="c1">// Don't need to check anything else, as if outputs.size == 1 then the output is equal to</span>
|
|
<span class="c1">// the input ignoring the owner field due to the grouping.</span>
|
|
<span class="p">}</span>
|
|
<span class="p">}</span>
|
|
|
|
<span class="k">is</span> <span class="n">Commands</span><span class="p">.</span><span class="n">Redeem</span> <span class="p">-></span> <span class="p">{</span>
|
|
<span class="c1">// Redemption of the paper requires movement of on-ledger cash.</span>
|
|
<span class="k">val</span> <span class="py">input</span> <span class="p">=</span> <span class="n">inputs</span><span class="p">.</span><span class="n">single</span><span class="p">()</span>
|
|
<span class="k">val</span> <span class="py">received</span> <span class="p">=</span> <span class="n">tx</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">input</span><span class="p">.</span><span class="n">owner</span><span class="p">)</span>
|
|
<span class="k">val</span> <span class="py">time</span> <span class="p">=</span> <span class="n">timestamp</span><span class="o">?.</span><span class="n">after</span> <span class="o">?:</span> <span class="k">throw</span> <span class="n">IllegalArgumentException</span><span class="p">(</span><span class="s">"Redemptions must be timestamped"</span><span class="p">)</span>
|
|
<span class="n">requireThat</span> <span class="p">{</span>
|
|
<span class="s">"the paper must have matured"</span> <span class="k">by</span> <span class="p">(</span><span class="n">time</span> <span class="p">>=</span> <span class="n">input</span><span class="p">.</span><span class="n">maturityDate</span><span class="p">)</span>
|
|
<span class="s">"the received amount equals the face value"</span> <span class="k">by</span> <span class="p">(</span><span class="n">received</span> <span class="p">==</span> <span class="n">input</span><span class="p">.</span><span class="n">faceValue</span><span class="p">)</span>
|
|
<span class="s">"the paper must be destroyed"</span> <span class="k">by</span> <span class="n">outputs</span><span class="p">.</span><span class="n">isEmpty</span><span class="p">()</span>
|
|
<span class="s">"the transaction is signed by the owner of the CP"</span> <span class="k">by</span> <span class="p">(</span><span class="n">input</span><span class="p">.</span><span class="n">owner</span> <span class="k">in</span> <span class="n">command</span><span class="p">.</span><span class="n">signers</span><span class="p">)</span>
|
|
<span class="p">}</span>
|
|
<span class="p">}</span>
|
|
|
|
<span class="k">is</span> <span class="n">Commands</span><span class="p">.</span><span class="n">Issue</span> <span class="p">-></span> <span class="p">{</span>
|
|
<span class="k">val</span> <span class="py">output</span> <span class="p">=</span> <span class="n">outputs</span><span class="p">.</span><span class="n">single</span><span class="p">()</span>
|
|
<span class="k">val</span> <span class="py">time</span> <span class="p">=</span> <span class="n">timestamp</span><span class="o">?.</span><span class="n">before</span> <span class="o">?:</span> <span class="k">throw</span> <span class="n">IllegalArgumentException</span><span class="p">(</span><span class="s">"Issuances must be timestamped"</span><span class="p">)</span>
|
|
<span class="n">requireThat</span> <span class="p">{</span>
|
|
<span class="c1">// Don't allow people to issue commercial paper under other entities identities.</span>
|
|
<span class="s">"output states are issued by a command signer"</span> <span class="k">by</span> <span class="p">(</span><span class="n">output</span><span class="p">.</span><span class="n">issuance</span><span class="p">.</span><span class="n">party</span><span class="p">.</span><span class="n">owningKey</span> <span class="k">in</span> <span class="n">command</span><span class="p">.</span><span class="n">signers</span><span class="p">)</span>
|
|
<span class="s">"output values sum to more than the inputs"</span> <span class="k">by</span> <span class="p">(</span><span class="n">output</span><span class="p">.</span><span class="n">faceValue</span><span class="p">.</span><span class="n">quantity</span> <span class="p">></span> <span class="m">0</span><span class="p">)</span>
|
|
<span class="s">"the maturity date is not in the past"</span> <span class="k">by</span> <span class="p">(</span><span class="n">time</span> <span class="p"><</span> <span class="n">output</span><span class="p">.</span><span class="n">maturityDate</span><span class="p">)</span>
|
|
<span class="c1">// Don't allow an existing CP state to be replaced by this issuance.</span>
|
|
<span class="s">"can't reissue an existing state"</span> <span class="k">by</span> <span class="n">inputs</span><span class="p">.</span><span class="n">isEmpty</span><span class="p">()</span>
|
|
<span class="p">}</span>
|
|
<span class="p">}</span>
|
|
|
|
<span class="k">else</span> <span class="p">-></span> <span class="k">throw</span> <span class="n">IllegalArgumentException</span><span class="p">(</span><span class="s">"Unrecognised command"</span><span class="p">)</span>
|
|
<span class="p">}</span>
|
|
<span class="p">}</span>
|
|
</pre></div>
|
|
</div>
|
|
<div class="highlight-java"><div class="highlight"><pre><span></span><span class="n">Timestamp</span> <span class="n">time</span> <span class="o">=</span> <span class="n">tx</span><span class="o">.</span><span class="na">getTimestamp</span><span class="o">();</span> <span class="c1">// Can be null/missing.</span>
|
|
<span class="k">for</span> <span class="o">(</span><span class="n">InOutGroup</span><span class="o"><</span><span class="n">State</span><span class="o">></span> <span class="n">group</span> <span class="o">:</span> <span class="n">groups</span><span class="o">)</span> <span class="o">{</span>
|
|
<span class="n">List</span><span class="o"><</span><span class="n">State</span><span class="o">></span> <span class="n">inputs</span> <span class="o">=</span> <span class="n">group</span><span class="o">.</span><span class="na">getInputs</span><span class="o">();</span>
|
|
<span class="n">List</span><span class="o"><</span><span class="n">State</span><span class="o">></span> <span class="n">outputs</span> <span class="o">=</span> <span class="n">group</span><span class="o">.</span><span class="na">getOutputs</span><span class="o">();</span>
|
|
|
|
<span class="c1">// For now do not allow multiple pieces of CP to trade in a single transaction. Study this more!</span>
|
|
<span class="n">State</span> <span class="n">input</span> <span class="o">=</span> <span class="n">single</span><span class="o">(</span><span class="n">filterIsInstance</span><span class="o">(</span><span class="n">inputs</span><span class="o">,</span> <span class="n">State</span><span class="o">.</span><span class="na">class</span><span class="o">));</span>
|
|
|
|
<span class="n">checkState</span><span class="o">(</span><span class="n">cmd</span><span class="o">.</span><span class="na">getSigners</span><span class="o">().</span><span class="na">contains</span><span class="o">(</span><span class="n">input</span><span class="o">.</span><span class="na">getOwner</span><span class="o">()),</span> <span class="s">"the transaction is signed by the owner of the CP"</span><span class="o">);</span>
|
|
|
|
<span class="k">if</span> <span class="o">(</span><span class="n">cmd</span><span class="o">.</span><span class="na">getValue</span><span class="o">()</span> <span class="k">instanceof</span> <span class="n">JavaCommercialPaper</span><span class="o">.</span><span class="na">Commands</span><span class="o">.</span><span class="na">Move</span><span class="o">)</span> <span class="o">{</span>
|
|
<span class="n">checkState</span><span class="o">(</span><span class="n">outputs</span><span class="o">.</span><span class="na">size</span><span class="o">()</span> <span class="o">==</span> <span class="mi">1</span><span class="o">,</span> <span class="s">"the state is propagated"</span><span class="o">);</span>
|
|
<span class="c1">// Don't need to check anything else, as if outputs.size == 1 then the output is equal to</span>
|
|
<span class="c1">// the input ignoring the owner field due to the grouping.</span>
|
|
<span class="o">}</span> <span class="k">else</span> <span class="k">if</span> <span class="o">(</span><span class="n">cmd</span><span class="o">.</span><span class="na">getValue</span><span class="o">()</span> <span class="k">instanceof</span> <span class="n">JavaCommercialPaper</span><span class="o">.</span><span class="na">Commands</span><span class="o">.</span><span class="na">Redeem</span><span class="o">)</span> <span class="o">{</span>
|
|
<span class="n">checkNotNull</span><span class="o">(</span><span class="n">timem</span> <span class="s">"must be timestamped"</span><span class="o">);</span>
|
|
<span class="n">Instant</span> <span class="n">t</span> <span class="o">=</span> <span class="n">time</span><span class="o">.</span><span class="na">getBefore</span><span class="o">();</span>
|
|
<span class="n">Amount</span><span class="o"><</span><span class="n">Issued</span><span class="o"><</span><span class="n">Currency</span><span class="o">>></span> <span class="n">received</span> <span class="o">=</span> <span class="n">CashKt</span><span class="o">.</span><span class="na">sumCashBy</span><span class="o">(</span><span class="n">tx</span><span class="o">.</span><span class="na">getOutputs</span><span class="o">(),</span> <span class="n">input</span><span class="o">.</span><span class="na">getOwner</span><span class="o">());</span>
|
|
|
|
<span class="n">checkState</span><span class="o">(</span><span class="n">received</span><span class="o">.</span><span class="na">equals</span><span class="o">(</span><span class="n">input</span><span class="o">.</span><span class="na">getFaceValue</span><span class="o">()),</span> <span class="s">"received amount equals the face value"</span><span class="o">);</span>
|
|
<span class="n">checkState</span><span class="o">(</span><span class="n">t</span><span class="o">.</span><span class="na">isBefore</span><span class="o">(</span><span class="n">input</span><span class="o">.</span><span class="na">getMaturityDate</span><span class="o">(),</span> <span class="s">"the paper must have matured"</span><span class="o">);</span>
|
|
<span class="n">checkState</span><span class="o">(</span><span class="n">outputs</span><span class="o">.</span><span class="na">isEmpty</span><span class="o">(),</span> <span class="s">"the paper must be destroyed"</span><span class="o">);</span>
|
|
<span class="o">}</span> <span class="k">else</span> <span class="k">if</span> <span class="o">(</span><span class="n">cmd</span><span class="o">.</span><span class="na">getValue</span><span class="o">()</span> <span class="k">instanceof</span> <span class="n">JavaCommercialPaper</span><span class="o">.</span><span class="na">Commands</span><span class="o">.</span><span class="na">Issue</span><span class="o">)</span> <span class="o">{</span>
|
|
<span class="c1">// .. etc .. (see Kotlin for full definition)</span>
|
|
<span class="o">}</span>
|
|
<span class="o">}</span>
|
|
</pre></div>
|
|
</div>
|
|
</div>
|
|
<p>This loop is the core logic of the contract.</p>
|
|
<p>The first line simply gets the timestamp out of the transaction. Timestamping of transactions is optional, so a time
|
|
may be missing here. We check for it being null later.</p>
|
|
<div class="admonition note">
|
|
<p class="first admonition-title">Note</p>
|
|
<p class="last">In future timestamping may be mandatory for all transactions.</p>
|
|
</div>
|
|
<div class="admonition warning">
|
|
<p class="first admonition-title">Warning</p>
|
|
<p class="last">In the Kotlin version as long as we write a comparison with the transaction time first the compiler will
|
|
verify we didn’t forget to check if it’s missing. Unfortunately due to the need for smooth Java interop, this
|
|
check won’t happen if we write e.g. <code class="docutils literal"><span class="pre">someDate</span> <span class="pre">></span> <span class="pre">time</span></code>, it has to be <code class="docutils literal"><span class="pre">time</span> <span class="pre"><</span> <span class="pre">someDate</span></code>. So it’s good practice to
|
|
always write the transaction timestamp first.</p>
|
|
</div>
|
|
<p>The first line (first three lines in Java) impose a requirement that there be a single piece of commercial paper in
|
|
this group. We do not allow multiple units of CP to be split or merged even if they are owned by the same owner. The
|
|
<code class="docutils literal"><span class="pre">single()</span></code> method is a static <em>extension method</em> defined by the Kotlin standard library: given a list, it throws an
|
|
exception if the list size is not 1, otherwise it returns the single item in that list. In Java, this appears as a
|
|
regular static method of the type familiar from many FooUtils type singleton classes and we have statically imported it
|
|
here. In Kotlin, it appears as a method that can be called on any JDK list. The syntax is slightly different but
|
|
behind the scenes, the code compiles to the same bytecodes.</p>
|
|
<p>Next, we check that the transaction was signed by the public key that’s marked as the current owner of the commercial
|
|
paper. Because the platform has already verified all the digital signatures before the contract begins execution,
|
|
all we have to do is verify that the owner’s public key was one of the keys that signed the transaction. The Java code
|
|
is straightforward: we are simply using the <code class="docutils literal"><span class="pre">Preconditions.checkState</span></code> method from Guava. The Kotlin version looks a little odd: we have a <em>requireThat</em> construct that looks like it’s
|
|
built into the language. In fact <em>requireThat</em> is an ordinary function provided by the platform’s contract API. Kotlin
|
|
supports the creation of <em>domain specific languages</em> through the intersection of several features of the language, and
|
|
we use it here to support the natural listing of requirements. To see what it compiles down to, look at the Java version.
|
|
Each <code class="docutils literal"><span class="pre">"string"</span> <span class="pre">by</span> <span class="pre">(expression)</span></code> statement inside a <code class="docutils literal"><span class="pre">requireThat</span></code> turns into an assertion that the given expression is
|
|
true, with an <code class="docutils literal"><span class="pre">IllegalStateException</span></code> being thrown that contains the string if not. It’s just another way to write out a regular
|
|
assertion, but with the English-language requirement being put front and center.</p>
|
|
<p>Next, we take one of two paths, depending on what the type of the command object is.</p>
|
|
<p>If the command is a <code class="docutils literal"><span class="pre">Move</span></code> command, then we simply verify that the output state is actually present: a move is not
|
|
allowed to delete the CP from the ledger. The grouping logic already ensured that the details are identical and haven’t
|
|
been changed, save for the public key of the owner.</p>
|
|
<p>If the command is a <code class="docutils literal"><span class="pre">Redeem</span></code> command, then the requirements are more complex:</p>
|
|
<ol class="arabic simple">
|
|
<li>We want to see that the face value of the CP is being moved as a cash claim against some party, that is, the
|
|
issuer of the CP is really paying back the face value.</li>
|
|
<li>The transaction must be happening after the maturity date.</li>
|
|
<li>The commercial paper must <em>not</em> be propagated by this transaction: it must be deleted, by the group having no
|
|
output state. This prevents the same CP being considered redeemable multiple times.</li>
|
|
</ol>
|
|
<p>To calculate how much cash is moving, we use the <code class="docutils literal"><span class="pre">sumCashBy</span></code> utility function. Again, this is an extension function,
|
|
so in Kotlin code it appears as if it was a method on the <code class="docutils literal"><span class="pre">List<Cash.State></span></code> type even though JDK provides no such
|
|
method. In Java we see its true nature: it is actually a static method named <code class="docutils literal"><span class="pre">CashKt.sumCashBy</span></code>. This method simply
|
|
returns an <code class="docutils literal"><span class="pre">Amount</span></code> object containing the sum of all the cash states in the transaction outputs that are owned by
|
|
that given public key, or throws an exception if there were no such states <em>or</em> if there were different currencies
|
|
represented in the outputs! So we can see that this contract imposes a limitation on the structure of a redemption
|
|
transaction: you are not allowed to move currencies in the same transaction that the CP does not involve. This
|
|
limitation could be addressed with better APIs, if it were to be a real limitation.</p>
|
|
<p>Finally, we support an <code class="docutils literal"><span class="pre">Issue</span></code> command, to create new instances of commercial paper on the ledger. It likewise
|
|
enforces various invariants upon the issuance.</p>
|
|
<p>This contract is simple and does not implement all the business logic a real commercial paper lifecycle
|
|
management program would. For instance, there is no logic requiring a signature from the issuer for redemption:
|
|
it is assumed that any transfer of money that takes place at the same time as redemption is good enough. Perhaps
|
|
that is something that should be tightened. Likewise, there is no logic handling what happens if the issuer has gone
|
|
bankrupt, if there is a dispute, and so on.</p>
|
|
<p>As the prototype evolves, these requirements will be explored and this tutorial updated to reflect improvements in the
|
|
contracts API.</p>
|
|
</div>
|
|
<div class="section" id="how-to-test-your-contract">
|
|
<h2>How to test your contract<a class="headerlink" href="#how-to-test-your-contract" title="Permalink to this headline">¶</a></h2>
|
|
<p>Of course, it is essential to unit test your new nugget of business logic to ensure that it behaves as you expect.
|
|
As contract code is just a regular Java function you could write out the logic entirely by hand in the usual
|
|
manner. But this would be inconvenient, and then you’d get bored of writing tests and that would be bad: you
|
|
might be tempted to skip a few.</p>
|
|
<p>To make contract testing more convenient Corda provides a language-like API for both Kotlin and Java that lets
|
|
you easily construct chains of transactions and verify that they either pass validation, or fail with a particular
|
|
error message.</p>
|
|
<p>Testing contracts with this domain specific language is covered in the separate tutorial, <a class="reference internal" href="tutorial-test-dsl.html"><span class="doc">Writing a contract test</span></a>.</p>
|
|
</div>
|
|
<div class="section" id="adding-a-generation-api-to-your-contract">
|
|
<h2>Adding a generation API to your contract<a class="headerlink" href="#adding-a-generation-api-to-your-contract" title="Permalink to this headline">¶</a></h2>
|
|
<p>Contract classes <strong>must</strong> provide a verify function, but they may optionally also provide helper functions to simplify
|
|
their usage. A simple class of functions most contracts provide are <em>generation functions</em>, which either create or
|
|
modify a transaction to perform certain actions (an action is normally mappable 1:1 to a command, but doesn’t have to
|
|
be so).</p>
|
|
<p>Generation may involve complex logic. For example, the cash contract has a <code class="docutils literal"><span class="pre">generateSpend</span></code> method that is given a set of
|
|
cash states and chooses a way to combine them together to satisfy the amount of money that is being sent. In the
|
|
immutable-state model that we are using ledger entries (states) can only be created and deleted, but never modified.
|
|
Therefore to send $1200 when we have only $900 and $500 requires combining both states together, and then creating
|
|
two new output states of $1200 and $200 back to ourselves. This latter state is called the <em>change</em> and is a concept
|
|
that should be familiar to anyone who has worked with Bitcoin.</p>
|
|
<p>As another example, we can imagine code that implements a netting algorithm may generate complex transactions that must
|
|
be signed by many people. Whilst such code might be too big for a single utility method (it’d probably be sized more
|
|
like a module), the basic concept is the same: preparation of a transaction using complex logic.</p>
|
|
<p>For our commercial paper contract however, the things that can be done with it are quite simple. Let’s start with
|
|
a method to wrap up the issuance process:</p>
|
|
<div class="codeset container">
|
|
<div class="highlight-kotlin"><div class="highlight"><pre><span></span><span class="k">fun</span> <span class="nf">generateIssue</span><span class="p">(</span><span class="n">issuance</span><span class="p">:</span> <span class="n">PartyAndReference</span><span class="p">,</span> <span class="n">faceValue</span><span class="p">:</span> <span class="n">Amount</span><span class="p"><</span><span class="n">Issued</span><span class="p"><</span><span class="n">Currency</span><span class="p">>>,</span> <span class="n">maturityDate</span><span class="p">:</span> <span class="n">Instant</span><span class="p">,</span>
|
|
<span class="n">notary</span><span class="p">:</span> <span class="n">Party</span><span class="p">):</span> <span class="n">TransactionBuilder</span> <span class="p">{</span>
|
|
<span class="k">val</span> <span class="py">state</span> <span class="p">=</span> <span class="n">State</span><span class="p">(</span><span class="n">issuance</span><span class="p">,</span> <span class="n">issuance</span><span class="p">.</span><span class="n">party</span><span class="p">.</span><span class="n">owningKey</span><span class="p">,</span> <span class="n">faceValue</span><span class="p">,</span> <span class="n">maturityDate</span><span class="p">)</span>
|
|
<span class="k">return</span> <span class="n">TransactionBuilder</span><span class="p">(</span><span class="n">notary</span> <span class="p">=</span> <span class="n">notary</span><span class="p">).</span><span class="n">withItems</span><span class="p">(</span><span class="n">state</span><span class="p">,</span> <span class="n">Command</span><span class="p">(</span><span class="n">Commands</span><span class="p">.</span><span class="n">Issue</span><span class="p">(),</span> <span class="n">issuance</span><span class="p">.</span><span class="n">party</span><span class="p">.</span><span class="n">owningKey</span><span class="p">))</span>
|
|
<span class="p">}</span>
|
|
</pre></div>
|
|
</div>
|
|
</div>
|
|
<p>We take a reference that points to the issuing party (i.e. the caller) and which can contain any internal
|
|
bookkeeping/reference numbers that we may require. The reference field is an ideal place to put (for example) a
|
|
join key. Then the face value of the paper, and the maturity date. It returns a <code class="docutils literal"><span class="pre">TransactionBuilder</span></code>.
|
|
A <code class="docutils literal"><span class="pre">TransactionBuilder</span></code> is one of the few mutable classes the platform provides. It allows you to add inputs,
|
|
outputs and commands to it and is designed to be passed around, potentially between multiple contracts.</p>
|
|
<div class="admonition note">
|
|
<p class="first admonition-title">Note</p>
|
|
<p class="last">Generation methods should ideally be written to compose with each other, that is, they should take a
|
|
<code class="docutils literal"><span class="pre">TransactionBuilder</span></code> as an argument instead of returning one, unless you are sure it doesn’t make sense to
|
|
combine this type of transaction with others. In this case, issuing CP at the same time as doing other things
|
|
would just introduce complexity that isn’t likely to be worth it, so we return a fresh object each time: instead,
|
|
an issuer should issue the CP (starting out owned by themselves), and then sell it in a separate transaction.</p>
|
|
</div>
|
|
<p>The function we define creates a <code class="docutils literal"><span class="pre">CommercialPaper.State</span></code> object that mostly just uses the arguments we were given,
|
|
but it fills out the owner field of the state to be the same public key as the issuing party.</p>
|
|
<p>The returned partial transaction has a <code class="docutils literal"><span class="pre">Command</span></code> object as a parameter. This is a container for any object
|
|
that implements the <code class="docutils literal"><span class="pre">CommandData</span></code> interface, along with a list of keys that are expected to sign this transaction. In this case,
|
|
issuance requires that the issuing party sign, so we put the key of the party there.</p>
|
|
<p>The <code class="docutils literal"><span class="pre">TransactionBuilder</span></code> has a convenience <code class="docutils literal"><span class="pre">withItems</span></code> method that takes a variable argument list. You can pass in
|
|
any <code class="docutils literal"><span class="pre">StateAndRef</span></code> (input), <code class="docutils literal"><span class="pre">ContractState</span></code> (output) or <code class="docutils literal"><span class="pre">Command</span></code> objects and it’ll build up the transaction
|
|
for you.</p>
|
|
<p>There’s one final thing to be aware of: we ask the caller to select a <em>notary</em> that controls this state and
|
|
prevents it from being double spent. You can learn more about this topic in the <a class="reference internal" href="consensus.html"><span class="doc">Consensus model</span></a> article.</p>
|
|
<div class="admonition note">
|
|
<p class="first admonition-title">Note</p>
|
|
<p class="last">For now, don’t worry about how to pick a notary. More infrastructure will come later to automate this
|
|
decision for you.</p>
|
|
</div>
|
|
<p>What about moving the paper, i.e. reassigning ownership to someone else?</p>
|
|
<div class="codeset container">
|
|
<div class="highlight-kotlin"><div class="highlight"><pre><span></span><span class="k">fun</span> <span class="nf">generateMove</span><span class="p">(</span><span class="n">tx</span><span class="p">:</span> <span class="n">TransactionBuilder</span><span class="p">,</span> <span class="n">paper</span><span class="p">:</span> <span class="n">StateAndRef</span><span class="p"><</span><span class="n">State</span><span class="p">>,</span> <span class="n">newOwner</span><span class="p">:</span> <span class="n">PublicKey</span><span class="p">)</span> <span class="p">{</span>
|
|
<span class="n">tx</span><span class="p">.</span><span class="n">addInputState</span><span class="p">(</span><span class="n">paper</span><span class="p">)</span>
|
|
<span class="n">tx</span><span class="p">.</span><span class="n">addOutputState</span><span class="p">(</span><span class="n">paper</span><span class="p">.</span><span class="n">state</span><span class="p">.</span><span class="k">data</span><span class="p">.</span><span class="n">withOwner</span><span class="p">(</span><span class="n">newOwner</span><span class="p">))</span>
|
|
<span class="n">tx</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">Commands</span><span class="p">.</span><span class="n">Move</span><span class="p">(),</span> <span class="n">paper</span><span class="p">.</span><span class="n">state</span><span class="p">.</span><span class="k">data</span><span class="p">.</span><span class="n">owner</span><span class="p">))</span>
|
|
<span class="p">}</span>
|
|
</pre></div>
|
|
</div>
|
|
</div>
|
|
<p>Here, the method takes a pre-existing <code class="docutils literal"><span class="pre">TransactionBuilder</span></code> and adds to it. This is correct because typically
|
|
you will want to combine a sale of CP atomically with the movement of some other asset, such as cash. So both
|
|
generate methods should operate on the same transaction. You can see an example of this being done in the unit tests
|
|
for the commercial paper contract.</p>
|
|
<p>The paper is given to us as a <code class="docutils literal"><span class="pre">StateAndRef<CommercialPaper.State></span></code> object. This is exactly what it sounds like:
|
|
a small object that has a (copy of) a state object, and also the (txhash, index) that indicates the location of this
|
|
state on the ledger.</p>
|
|
<p>We add the existing paper state as an input, the same paper state with the owner field adjusted as an output,
|
|
and finally a move command that has the old owner’s public key: this is what forces the current owner’s signature
|
|
to be present on the transaction, and is what’s checked by the contract.</p>
|
|
<p>Finally, we can do redemption.</p>
|
|
<div class="codeset container">
|
|
<div class="highlight-kotlin"><div class="highlight"><pre><span></span><span class="n">@Throws</span><span class="p">(</span><span class="n">InsufficientBalanceException</span><span class="o">::</span><span class="k">class</span><span class="p">)</span>
|
|
<span class="k">fun</span> <span class="nf">generateRedeem</span><span class="p">(</span><span class="n">tx</span><span class="p">:</span> <span class="n">TransactionBuilder</span><span class="p">,</span> <span class="n">paper</span><span class="p">:</span> <span class="n">StateAndRef</span><span class="p"><</span><span class="n">State</span><span class="p">>,</span> <span class="n">wallet</span><span class="p">:</span> <span class="n">Wallet</span><span class="p">)</span> <span class="p">{</span>
|
|
<span class="c1">// Add the cash movement using the states in our wallet.</span>
|
|
<span class="n">Cash</span><span class="p">().</span><span class="n">generateSpend</span><span class="p">(</span><span class="n">tx</span><span class="p">,</span> <span class="n">paper</span><span class="p">.</span><span class="n">state</span><span class="p">.</span><span class="k">data</span><span class="p">.</span><span class="n">faceValue</span><span class="p">.</span><span class="n">withoutIssuer</span><span class="p">(),</span> <span class="n">paper</span><span class="p">.</span><span class="n">state</span><span class="p">.</span><span class="k">data</span><span class="p">.</span><span class="n">owner</span><span class="p">,</span> <span class="n">wallet</span><span class="p">.</span><span class="n">statesOfType</span><span class="p"><</span><span class="n">Cash</span><span class="p">.</span><span class="n">State</span><span class="p">>())</span>
|
|
<span class="n">tx</span><span class="p">.</span><span class="n">addInputState</span><span class="p">(</span><span class="n">paper</span><span class="p">)</span>
|
|
<span class="n">tx</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">Commands</span><span class="p">.</span><span class="n">Redeem</span><span class="p">(),</span> <span class="n">paper</span><span class="p">.</span><span class="n">state</span><span class="p">.</span><span class="k">data</span><span class="p">.</span><span class="n">owner</span><span class="p">))</span>
|
|
<span class="p">}</span>
|
|
</pre></div>
|
|
</div>
|
|
</div>
|
|
<p>Here we can see an example of composing contracts together. When an owner wishes to redeem the commercial paper, the
|
|
issuer (i.e. the caller) must gather cash from its wallet and send the face value to the owner of the paper.</p>
|
|
<div class="admonition note">
|
|
<p class="first admonition-title">Note</p>
|
|
<p class="last">This contract has no explicit concept of rollover.</p>
|
|
</div>
|
|
<p>The <em>wallet</em> is a concept that may be familiar from Bitcoin and Ethereum. It is simply a set of states (such as cash) that are
|
|
owned by the caller. Here, we use the wallet to update the partial transaction we are handed with a movement of cash
|
|
from the issuer of the commercial paper to the current owner. If we don’t have enough quantity of cash in our wallet,
|
|
an exception is thrown. Then we add the paper itself as an input, but, not an output (as we wish to remove it
|
|
from the ledger). Finally, we add a Redeem command that should be signed by the owner of the commercial paper.</p>
|
|
<div class="admonition warning">
|
|
<p class="first admonition-title">Warning</p>
|
|
<p class="last">The amount we pass to the <code class="docutils literal"><span class="pre">generateSpend</span></code> function has to be treated first with <code class="docutils literal"><span class="pre">withoutIssuer</span></code>.
|
|
This reflects the fact that the way we handle issuer constraints is still evolving; the commercial paper
|
|
contract requires payment in the form of a currency issued by a specific party (e.g. the central bank,
|
|
or the issuers own bank perhaps). But the wallet wants to assemble spend transactions using cash states from
|
|
any issuer, thus we must strip it here. This represents a design mismatch that we will resolve in future
|
|
versions with a more complete way to express issuer constraints.</p>
|
|
</div>
|
|
<p>A <code class="docutils literal"><span class="pre">TransactionBuilder</span></code> is not by itself ready to be used anywhere, so first, we must convert it to something that
|
|
is recognised by the network. The most important next step is for the participating entities to sign it using the
|
|
<code class="docutils literal"><span class="pre">signWith()</span></code> method. This takes a keypair, serialises the transaction, signs the serialised form and then stores the
|
|
signature inside the <code class="docutils literal"><span class="pre">TransactionBuilder</span></code>. Once all parties have signed, you can call <code class="docutils literal"><span class="pre">TransactionBuilder.toSignedTransaction()</span></code>
|
|
to get a <code class="docutils literal"><span class="pre">SignedTransaction</span></code> object.</p>
|
|
<p>You can see how transactions flow through the different stages of construction by examining the commercial paper
|
|
unit tests.</p>
|
|
</div>
|
|
<div class="section" id="how-multi-party-transactions-are-constructed-and-transmitted">
|
|
<h2>How multi-party transactions are constructed and transmitted<a class="headerlink" href="#how-multi-party-transactions-are-constructed-and-transmitted" title="Permalink to this headline">¶</a></h2>
|
|
<p>OK, so now we know how to define the rules of the ledger, and we know how to construct transactions that satisfy
|
|
those rules ... and if all we were doing was maintaining our own data that might be enough. But we aren’t: Corda
|
|
is about keeping many different parties all in sync with each other.</p>
|
|
<p>In a classical blockchain system all data is transmitted to everyone and if you want to do something fancy, like
|
|
a multi-party transaction, you’re on your own. In Corda data is transmitted only to parties that need it and
|
|
multi-party transactions are a way of life, so we provide lots of support for managing them.</p>
|
|
<p>You can learn how transactions are moved between peers and taken through the build-sign-notarise-broadcast
|
|
process in a separate tutorial, <a class="reference internal" href="protocol-state-machines.html"><span class="doc">Protocol state machines</span></a>.</p>
|
|
</div>
|
|
<div class="section" id="non-asset-oriented-smart-contracts">
|
|
<h2>Non-asset-oriented smart contracts<a class="headerlink" href="#non-asset-oriented-smart-contracts" title="Permalink to this headline">¶</a></h2>
|
|
<p>Although this tutorial covers how to implement an owned asset, there is no requirement that states and code contracts
|
|
<em>must</em> be concerned with ownership of an asset. It is better to think of states as representing useful facts about the
|
|
world, and (code) contracts as imposing logical relations on how facts combine to produce new facts. Alternatively
|
|
you can imagine that states are like rows in a relational database and contracts are like stored procedures and
|
|
relational constraints.</p>
|
|
<p>When writing a contract that handles deal-like entities rather than asset-like entities, you may wish to refer
|
|
to “<a class="reference internal" href="contract-irs.html"><span class="doc">Interest Rate Swaps</span></a>” and the accompanying source code. Whilst all the concepts are the same, deals are
|
|
typically not splittable or mergeable and thus you don’t have to worry much about grouping of states.</p>
|
|
</div>
|
|
<div class="section" id="making-things-happen-at-a-particular-time">
|
|
<h2>Making things happen at a particular time<a class="headerlink" href="#making-things-happen-at-a-particular-time" title="Permalink to this headline">¶</a></h2>
|
|
<p>It would be nice if you could program your node to automatically redeem your commercial paper as soon as it matures.
|
|
Corda provides a way for states to advertise scheduled events that should occur in future. Whilst this information
|
|
is by default ignored, if the corresponding <em>Cordapp</em> is installed and active in your node, and if the state is
|
|
considered relevant by your wallet (e.g. because you own it), then the node can automatically begin the process
|
|
of creating a transaction and taking it through the life cycle. You can learn more about this in the article
|
|
“<a class="reference internal" href="event-scheduling.html"><span class="doc">Event scheduling</span></a>”.</p>
|
|
</div>
|
|
<div class="section" id="encumbrances">
|
|
<h2>Encumbrances<a class="headerlink" href="#encumbrances" title="Permalink to this headline">¶</a></h2>
|
|
<p>All contract states may be <em>encumbered</em> by up to one other state, which we call an <strong>encumbrance</strong>.</p>
|
|
<p>The encumbrance state, if present, forces additional controls over the encumbered state, since the encumbrance state contract
|
|
will also be verified during the execution of the transaction. For example, a contract state could be encumbered
|
|
with a time-lock contract state; the state is then only processable in a transaction that verifies that the time
|
|
specified in the encumbrance time-lock has passed.</p>
|
|
<p>The encumbered state refers to its encumbrance by index, and the referred encumbrance state
|
|
is an output state in a particular position on the same transaction that created the encumbered state. Note that an
|
|
encumbered state that is being consumed must have its encumbrance consumed in the same transaction, otherwise the
|
|
transaction is not valid.</p>
|
|
<p>The encumbrance reference is optional in the <code class="docutils literal"><span class="pre">ContractState</span></code> interface:</p>
|
|
<div class="codeset container">
|
|
<div class="highlight-kotlin"><div class="highlight"><pre><span></span><span class="k">val</span> <span class="py">encumbrance</span><span class="p">:</span> <span class="n">Int</span><span class="p">?</span> <span class="k">get</span><span class="p">()</span> <span class="p">=</span> <span class="k">null</span>
|
|
</pre></div>
|
|
</div>
|
|
<div class="highlight-java"><div class="highlight"><pre><span></span><span class="nd">@Nullable</span>
|
|
<span class="nd">@Override</span>
|
|
<span class="kd">public</span> <span class="n">Integer</span> <span class="nf">getEncumbrance</span><span class="o">()</span> <span class="o">{</span>
|
|
<span class="k">return</span> <span class="kc">null</span><span class="o">;</span>
|
|
<span class="o">}</span>
|
|
</pre></div>
|
|
</div>
|
|
</div>
|
|
<p>The time-lock contract mentioned above can be implemented very simply:</p>
|
|
<div class="codeset container">
|
|
<div class="highlight-kotlin"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">TestTimeLock</span> <span class="p">:</span> <span class="n">Contract</span> <span class="p">{</span>
|
|
<span class="p">...</span>
|
|
<span class="k">override</span> <span class="k">fun</span> <span class="nf">verify</span><span class="p">(</span><span class="n">tx</span><span class="p">:</span> <span class="n">TransactionForContract</span><span class="p">)</span> <span class="p">{</span>
|
|
<span class="k">val</span> <span class="py">time</span> <span class="p">=</span> <span class="n">tx</span><span class="p">.</span><span class="n">timestamp</span><span class="p">.</span><span class="n">before</span> <span class="o">?:</span> <span class="k">throw</span> <span class="n">IllegalStateException</span><span class="p">(...)</span>
|
|
<span class="p">...</span>
|
|
<span class="n">requireThat</span> <span class="p">{</span>
|
|
<span class="s">"the time specified in the time-lock has passed"</span> <span class="k">by</span>
|
|
<span class="p">(</span><span class="n">time</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">filterIsInstance</span><span class="p"><</span><span class="n">TestTimeLock</span><span class="p">.</span><span class="n">State</span><span class="p">>().</span><span class="n">single</span><span class="p">().</span><span class="n">validFrom</span><span class="p">)</span>
|
|
<span class="p">}</span>
|
|
<span class="p">}</span>
|
|
<span class="p">...</span>
|
|
<span class="p">}</span>
|
|
</pre></div>
|
|
</div>
|
|
</div>
|
|
<p>We can then set up an encumbered state:</p>
|
|
<div class="codeset container">
|
|
<div class="highlight-kotlin"><div class="highlight"><pre><span></span>val encumberedState = Cash.State(amount = 1000.DOLLARS `issued by` defaultIssuer, owner = DUMMY_PUBKEY_1, encumbrance = 1)
|
|
val fourPmTimelock = TestTimeLock.State(Instant.parse("2015-04-17T16:00:00.00Z"))
|
|
</pre></div>
|
|
</div>
|
|
</div>
|
|
<p>When we construct a transaction that generates the encumbered state, we must place the encumbrance in the corresponding output
|
|
position of that transaction. And when we subsequently consume that encumbered state, the same encumbrance state must be
|
|
available somewhere within the input set of states.</p>
|
|
<p>In future, we will consider the concept of a <em>covenant</em>. This is where the encumbrance travels alongside each iteration of
|
|
the encumbered state. For example, a cash state may be encumbered with a <em>domicile</em> encumbrance, which checks the domicile of
|
|
the identity of the owner that the cash state is being moved to, in order to uphold sanction screening regulations, and prevent
|
|
cash being paid to parties domiciled in e.g. North Korea. In this case, the encumbrance should be permanently attached to
|
|
the all future cash states stemming from this one.</p>
|
|
<p>We will also consider marking states that are capable of being encumbrances as such. This will prevent states being used
|
|
as encumbrances inadvertently. For example, the time-lock above would be usable as an encumbrance, but it makes no sense to
|
|
be able to encumber a cash state with another one.</p>
|
|
</div>
|
|
<div class="section" id="clauses">
|
|
<h2>Clauses<a class="headerlink" href="#clauses" title="Permalink to this headline">¶</a></h2>
|
|
<p>It is typical for slightly different contracts to have lots of common logic that can be shared. For example, the
|
|
concept of being issued, being exited and being upgraded are all usually required in any contract. Corda calls these
|
|
frequently needed chunks of logic “clauses”, and they can simplify development considerably.</p>
|
|
<p>Clauses and how to use them are addressed in the next tutorial, “<a class="reference internal" href="tutorial-contract-clauses.html"><span class="doc">Writing a contract using clauses</span></a>”.</p>
|
|
</div>
|
|
</div>
|
|
|
|
|
|
</div>
|
|
</div>
|
|
<footer>
|
|
|
|
<div class="rst-footer-buttons" role="navigation" aria-label="footer navigation">
|
|
|
|
<a href="tutorial-contract-clauses.html" class="btn btn-neutral float-right" title="Writing a contract using clauses" accesskey="n">Next <span class="fa fa-arrow-circle-right"></span></a>
|
|
|
|
|
|
<a href="where-to-start.html" class="btn btn-neutral" title="Where to start" accesskey="p"><span class="fa fa-arrow-circle-left"></span> Previous</a>
|
|
|
|
</div>
|
|
|
|
|
|
<hr/>
|
|
|
|
<div role="contentinfo">
|
|
<p>
|
|
© Copyright 2016, Distributed Ledger Group, LLC.
|
|
|
|
</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> |