mirror of
https://github.com/corda/corda.git
synced 2024-12-22 14:22:28 +00:00
709 lines
57 KiB
HTML
709 lines
57 KiB
HTML
<!-- If you edit this, then please make the same changes to layout_for_doc_website.html, as that is used for the web
|
||
doc site generation which we put analytics tracking on to identify any potential problem pages -->
|
||
|
||
|
||
|
||
|
||
<!DOCTYPE html>
|
||
<!--[if IE 8]><html class="no-js lt-ie9" lang="en" > <![endif]-->
|
||
<!--[if gt IE 8]><!--> <html class="no-js" lang="en" > <!--<![endif]-->
|
||
<head>
|
||
<meta charset="utf-8">
|
||
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||
|
||
<title>Building Transactions — 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 flows" href="flow-state-machines.html"/>
|
||
<link rel="prev" title="Client RPC API tutorial" href="tutorial-clientrpc-api.html"/>
|
||
|
||
|
||
<script src="_static/js/modernizr.min.js"></script>
|
||
|
||
</head>
|
||
|
||
<body class="wy-body-for-nav" role="document">
|
||
|
||
<div class="wy-grid-for-nav">
|
||
|
||
|
||
<nav data-toggle="wy-nav-shift" class="wy-nav-side">
|
||
<div class="wy-side-scroll">
|
||
<div class="wy-side-nav-search">
|
||
|
||
|
||
|
||
|
||
<a href="index.html" class="icon icon-home"> R3 Corda
|
||
|
||
|
||
|
||
</a>
|
||
|
||
|
||
|
||
|
||
<div class="version">
|
||
latest
|
||
</div>
|
||
|
||
|
||
|
||
|
||
<div role="search">
|
||
<form id="rtd-search-form" class="wy-form" action="search.html" method="get">
|
||
<input type="text" name="q" placeholder="Search docs" />
|
||
<input type="hidden" name="check_keywords" value="yes" />
|
||
<input type="hidden" name="area" value="default" />
|
||
</form>
|
||
</div>
|
||
|
||
|
||
<br>
|
||
<a href="api/index.html">API reference</a>
|
||
<br>
|
||
<a href="https://discourse.corda.net">Discourse Forums</a>
|
||
<br>
|
||
<a href="http://slack.corda.net">Slack</a>
|
||
<br>
|
||
|
||
</div>
|
||
|
||
<div class="wy-menu wy-menu-vertical" data-spy="affix" role="navigation" aria-label="main navigation">
|
||
|
||
|
||
|
||
<p class="caption"><span class="caption-text">Getting started</span></p>
|
||
<ul>
|
||
<li class="toctree-l1"><a class="reference internal" href="inthebox.html">What’s included?</a></li>
|
||
<li class="toctree-l1"><a class="reference internal" href="getting-set-up.html">Getting set up</a></li>
|
||
<li class="toctree-l1"><a class="reference internal" href="getting-set-up-fault-finding.html">Getting set up: troubleshooting</a></li>
|
||
<li class="toctree-l1"><a class="reference internal" href="running-the-demos.html">Running the demos</a></li>
|
||
<li class="toctree-l1"><a class="reference internal" href="CLI-vs-IDE.html">CLI vs IDE</a></li>
|
||
</ul>
|
||
<p class="caption"><span class="caption-text">Key concepts</span></p>
|
||
<ul>
|
||
<li class="toctree-l1"><a class="reference internal" href="data-model.html">Data model</a></li>
|
||
<li class="toctree-l1"><a class="reference internal" href="transaction-data-types.html">Data types</a></li>
|
||
<li class="toctree-l1"><a class="reference internal" href="merkle-trees.html">Transaction tear-offs</a></li>
|
||
<li class="toctree-l1"><a class="reference internal" href="consensus.html">Consensus model</a></li>
|
||
<li class="toctree-l1"><a class="reference internal" href="clauses.html">Clauses key concepts</a></li>
|
||
</ul>
|
||
<p class="caption"><span class="caption-text">CorDapps</span></p>
|
||
<ul>
|
||
<li class="toctree-l1"><a class="reference internal" href="creating-a-cordapp.html">CorDapps Background</a></li>
|
||
<li class="toctree-l1"><a class="reference internal" href="creating-a-cordapp.html#gradle-plugins-for-cordapps">Gradle plugins for CorDapps</a></li>
|
||
<li class="toctree-l1"><a class="reference internal" href="tutorial-cordapp.html">The CorDapp Template</a></li>
|
||
<li class="toctree-l1"><a class="reference internal" href="tutorial-cordapp.html#building-the-cordapp-template">Building the CorDapp template</a></li>
|
||
<li class="toctree-l1"><a class="reference internal" href="tutorial-cordapp.html#running-the-cordapp-template">Running the CorDapp template</a></li>
|
||
<li class="toctree-l1"><a class="reference internal" href="tutorial-cordapp.html#interacting-with-the-cordapp-template">Interacting with the CorDapp template</a></li>
|
||
<li class="toctree-l1"><a class="reference internal" href="tutorial-cordapp.html#extending-the-cordapp-template">Extending the CorDapp template</a></li>
|
||
</ul>
|
||
<p class="caption"><span class="caption-text">The Corda node</span></p>
|
||
<ul>
|
||
<li class="toctree-l1"><a class="reference internal" href="clientrpc.html">Client RPC</a></li>
|
||
<li class="toctree-l1"><a class="reference internal" href="messaging.html">Networking and messaging</a></li>
|
||
<li class="toctree-l1"><a class="reference internal" href="persistence.html">Persistence</a></li>
|
||
<li class="toctree-l1"><a class="reference internal" href="node-administration.html">Node administration</a></li>
|
||
<li class="toctree-l1"><a class="reference internal" href="corda-configuration-file.html">Node configuration</a></li>
|
||
<li class="toctree-l1"><a class="reference internal" href="corda-plugins.html">The Corda plugin framework</a></li>
|
||
<li class="toctree-l1"><a class="reference internal" href="node-services.html">Brief introduction to the node services</a></li>
|
||
<li class="toctree-l1"><a class="reference internal" href="node-explorer.html">Node Explorer</a></li>
|
||
<li class="toctree-l1"><a class="reference internal" href="permissioning.html">Network permissioning</a></li>
|
||
</ul>
|
||
<p class="caption"><span class="caption-text">Tutorials</span></p>
|
||
<ul class="current">
|
||
<li class="toctree-l1"><a class="reference internal" href="tutorial-contract.html">Writing a contract</a></li>
|
||
<li class="toctree-l1"><a class="reference internal" href="tutorial-contract-clauses.html">Writing a contract using clauses</a></li>
|
||
<li class="toctree-l1"><a class="reference internal" href="tutorial-test-dsl.html">Writing a contract test</a></li>
|
||
<li class="toctree-l1"><a class="reference internal" href="tutorial-integration-testing.html">Integration Test Tutorial</a></li>
|
||
<li class="toctree-l1"><a class="reference internal" href="tutorial-clientrpc-api.html">Client RPC API tutorial</a></li>
|
||
<li class="toctree-l1 current"><a class="current reference internal" href="#">Building Transactions</a><ul>
|
||
<li class="toctree-l2"><a class="reference internal" href="#introduction">Introduction</a></li>
|
||
<li class="toctree-l2"><a class="reference internal" href="#the-basic-lifecycle-of-transactions">The Basic Lifecycle Of Transactions</a></li>
|
||
<li class="toctree-l2"><a class="reference internal" href="#gathering-inputs">Gathering Inputs</a></li>
|
||
<li class="toctree-l2"><a class="reference internal" href="#generating-commands">Generating Commands</a></li>
|
||
<li class="toctree-l2"><a class="reference internal" href="#generating-outputs">Generating Outputs</a></li>
|
||
<li class="toctree-l2"><a class="reference internal" href="#building-the-wiretransaction">Building the WireTransaction</a></li>
|
||
<li class="toctree-l2"><a class="reference internal" href="#completing-the-signedtransaction">Completing the SignedTransaction</a></li>
|
||
<li class="toctree-l2"><a class="reference internal" href="#committing-the-transaction">Committing the Transaction</a></li>
|
||
<li class="toctree-l2"><a class="reference internal" href="#partially-visible-transactions">Partially Visible Transactions</a></li>
|
||
</ul>
|
||
</li>
|
||
<li class="toctree-l1"><a class="reference internal" href="flow-state-machines.html">Writing flows</a></li>
|
||
<li class="toctree-l1"><a class="reference internal" href="flow-testing.html">Writing flow tests</a></li>
|
||
<li class="toctree-l1"><a class="reference internal" href="running-a-notary.html">Running a notary service</a></li>
|
||
<li class="toctree-l1"><a class="reference internal" href="using-a-notary.html">Using a notary service</a></li>
|
||
<li class="toctree-l1"><a class="reference internal" href="oracles.html">Writing oracle services</a></li>
|
||
<li class="toctree-l1"><a class="reference internal" href="oracles.html#implementing-an-oracle-with-continuously-varying-data">Implementing an oracle with continuously varying data</a></li>
|
||
<li class="toctree-l1"><a class="reference internal" href="oracles.html#using-an-oracle">Using an oracle</a></li>
|
||
<li class="toctree-l1"><a class="reference internal" href="tutorial-attachments.html">Using attachments</a></li>
|
||
<li class="toctree-l1"><a class="reference internal" href="event-scheduling.html">Event scheduling</a></li>
|
||
</ul>
|
||
<p class="caption"><span class="caption-text">Other</span></p>
|
||
<ul>
|
||
<li class="toctree-l1"><a class="reference internal" href="network-simulator.html">Network Simulator</a></li>
|
||
<li class="toctree-l1"><a class="reference internal" href="initial-margin-agreement.html">Initial margin agreements</a></li>
|
||
</ul>
|
||
<p class="caption"><span class="caption-text">Component library</span></p>
|
||
<ul>
|
||
<li class="toctree-l1"><a class="reference internal" href="contract-catalogue.html">Contract catalogue</a></li>
|
||
<li class="toctree-l1"><a class="reference internal" href="contract-irs.html">Interest rate swaps</a></li>
|
||
</ul>
|
||
<p class="caption"><span class="caption-text">Appendix</span></p>
|
||
<ul>
|
||
<li class="toctree-l1"><a class="reference internal" href="loadtesting.html">Load testing</a></li>
|
||
<li class="toctree-l1"><a class="reference internal" href="setting-up-a-corda-network.html">Introduction - What is a corda network?</a></li>
|
||
<li class="toctree-l1"><a class="reference internal" href="setting-up-a-corda-network.html#setting-up-your-own-network">Setting up your own network</a></li>
|
||
<li class="toctree-l1"><a class="reference internal" href="secure-coding-guidelines.html">Secure coding guidelines</a></li>
|
||
<li class="toctree-l1"><a class="reference internal" href="release-process.html">Release process</a></li>
|
||
<li class="toctree-l1"><a class="reference internal" href="release-process.html#steps-to-cut-a-release">Steps to cut a release</a></li>
|
||
<li class="toctree-l1"><a class="reference internal" href="release-notes.html">Release notes</a></li>
|
||
<li class="toctree-l1"><a class="reference internal" href="codestyle.html">Code style guide</a></li>
|
||
<li class="toctree-l1"><a class="reference internal" href="building-the-docs.html">Building the documentation</a></li>
|
||
<li class="toctree-l1"><a class="reference internal" href="publishing-corda.html">Publishing Corda</a></li>
|
||
<li class="toctree-l1"><a class="reference internal" href="azure-vm.html">Working with the Corda Demo on Azure Marketplace</a></li>
|
||
</ul>
|
||
<p class="caption"><span class="caption-text">Glossary</span></p>
|
||
<ul>
|
||
<li class="toctree-l1"><a class="reference internal" href="glossary.html">Glossary</a></li>
|
||
</ul>
|
||
|
||
|
||
|
||
</div>
|
||
</div>
|
||
</nav>
|
||
|
||
<section data-toggle="wy-nav-shift" class="wy-nav-content-wrap">
|
||
|
||
|
||
<nav class="wy-nav-top" role="navigation" aria-label="top navigation">
|
||
<i data-toggle="wy-nav-top" class="fa fa-bars"></i>
|
||
<a href="index.html">R3 Corda</a>
|
||
</nav>
|
||
|
||
|
||
|
||
<div class="wy-nav-content">
|
||
<div class="rst-content">
|
||
|
||
|
||
|
||
|
||
|
||
|
||
<div role="navigation" aria-label="breadcrumbs navigation">
|
||
<ul class="wy-breadcrumbs">
|
||
<li><a href="index.html">Docs</a> »</li>
|
||
|
||
<li>Building Transactions</li>
|
||
<li class="wy-breadcrumbs-aside">
|
||
|
||
|
||
<a href="_sources/tutorial-building-transactions.txt" rel="nofollow"> View page source</a>
|
||
|
||
|
||
</li>
|
||
</ul>
|
||
<hr/>
|
||
</div>
|
||
<div role="main" class="document" itemscope="itemscope" itemtype="http://schema.org/Article">
|
||
<div itemprop="articleBody">
|
||
|
||
<div class="section" id="building-transactions">
|
||
<h1>Building Transactions<a class="headerlink" href="#building-transactions" title="Permalink to this headline">¶</a></h1>
|
||
<div class="section" id="introduction">
|
||
<h2>Introduction<a class="headerlink" href="#introduction" title="Permalink to this headline">¶</a></h2>
|
||
<p>Understanding and implementing transactions in Corda is key to building
|
||
and implementing real world smart contracts. It is only through
|
||
construction of valid Corda transactions containing appropriate data
|
||
that nodes on the ledger can map real world business objects into a
|
||
shared digital view of the data in the Corda ledger. More importantly as
|
||
the developer of new smart contracts it is the code which determines
|
||
what data is well formed and what data should be rejected as mistakes,
|
||
or to prevent malicious activity. This document details some of the
|
||
considerations and APIs used to when constructing transactions as part
|
||
of a flow.</p>
|
||
</div>
|
||
<div class="section" id="the-basic-lifecycle-of-transactions">
|
||
<h2>The Basic Lifecycle Of Transactions<a class="headerlink" href="#the-basic-lifecycle-of-transactions" title="Permalink to this headline">¶</a></h2>
|
||
<p>Transactions in Corda are constructed in stages and contain a number of
|
||
elements. In particular a transaction’s core data structure is the
|
||
<code class="docutils literal"><span class="pre">net.corda.core.transactions.WireTransaction</span></code>, which is usually
|
||
manipulated via a
|
||
<code class="docutils literal"><span class="pre">net.corda.core.contracts.General.TransactionBuilder</span></code> and contains:</p>
|
||
<p>1. A set of Input state references that will be consumed by the final
|
||
accepted transaction.</p>
|
||
<p>2. A set of Output states to create/replace the consumed states and thus
|
||
become the new latest versions of data on the ledger.</p>
|
||
<p>3. A set of <code class="docutils literal"><span class="pre">Attachment</span></code> items which can contain legal documents, contract
|
||
code, or private encrypted sections as an extension beyond the native
|
||
contract states.</p>
|
||
<p>4. A set of <code class="docutils literal"><span class="pre">Command</span></code> items which give a context to the type of ledger
|
||
transition that is encoded in the transaction. Also each command has an
|
||
associated set of signer keys, which will be required to sign the
|
||
transaction.</p>
|
||
<p>5. A signers list, which is populated by the <code class="docutils literal"><span class="pre">TransactionBuilder</span></code> to
|
||
be the union of the signers on the individual Command objects.</p>
|
||
<p>6. A notary identity to specify the Notary node which is tracking the
|
||
state consumption. (If the input states are registered with different
|
||
notary nodes the flow will have to insert additional <code class="docutils literal"><span class="pre">NotaryChange</span></code>
|
||
transactions to migrate the states across to a consistent notary node,
|
||
before being allowed to mutate any states.)</p>
|
||
<p>7. Optionally a timestamp that can used in the Notary to time bound the
|
||
period in which the proposed transaction stays valid.</p>
|
||
<p>Typically, the <code class="docutils literal"><span class="pre">WireTransaction</span></code> should be regarded as a proposal and
|
||
may need to be exchanged back and forth between parties before it can be
|
||
fully populated. This is an immediate consequence of the Corda privacy
|
||
model, which means that the input states are likely to be unknown to the
|
||
other node.</p>
|
||
<p>Once the proposed data is fully populated the flow code should freeze
|
||
the <code class="docutils literal"><span class="pre">WireTransaction</span></code> and form a <code class="docutils literal"><span class="pre">SignedTransaction</span></code>. This is key to
|
||
the ledger agreement process, as once a flow has attached a node’s
|
||
signature it has stated that all details of the transaction are
|
||
acceptable to it. A flow should take care not to attach signatures to
|
||
intermediate data, which might be maliciously used to construct a
|
||
different <code class="docutils literal"><span class="pre">SignedTransaction</span></code>. For instance in a foreign exchange
|
||
scenario we shouldn’t send a <code class="docutils literal"><span class="pre">SignedTransaction</span></code> with only our sell
|
||
side populated as that could be used to take the money without the
|
||
expected return of the other currency. Also, it is best practice for
|
||
flows to receive back the <code class="docutils literal"><span class="pre">DigitalSignature.WithKey</span></code> of other parties
|
||
rather than a full <code class="docutils literal"><span class="pre">SignedTransaction</span></code> objects, because otherwise we
|
||
have to separately check that this is still the same
|
||
<code class="docutils literal"><span class="pre">SignedTransaction</span></code> and not a malicious substitute.</p>
|
||
<p>The final stage of committing the transaction to the ledger is to
|
||
notarise the <code class="docutils literal"><span class="pre">SignedTransaction</span></code>, distribute this to all appropriate
|
||
parties and record the data into the ledger. These actions are best
|
||
delegated to the <code class="docutils literal"><span class="pre">FinalityFlow</span></code>, rather than calling the inidividual
|
||
steps manually. However, do note that the final broadcast to the other
|
||
nodes is asynchronous, so care must be used in unit testing to
|
||
correctly await the Vault updates.</p>
|
||
</div>
|
||
<div class="section" id="gathering-inputs">
|
||
<h2>Gathering Inputs<a class="headerlink" href="#gathering-inputs" title="Permalink to this headline">¶</a></h2>
|
||
<p>One of the first steps to forming a transaction is gathering the set of
|
||
input references. This process will clearly vary according to the nature
|
||
of the business process being captured by the smart contract and the
|
||
parameterised details of the request. However, it will generally involve
|
||
searching the Vault via the <code class="docutils literal"><span class="pre">VaultService</span></code> interface on the
|
||
<code class="docutils literal"><span class="pre">ServiceHub</span></code> to locate the input states.</p>
|
||
<p>To give a few more specific details consider two simplified real world
|
||
scenarios. First, a basic foreign exchange Cash transaction. This
|
||
transaction needs to locate a set of funds to exchange. A flow
|
||
modelling this is implemented in <code class="docutils literal"><span class="pre">FxTransactionBuildTutorial.kt</span></code>.
|
||
Second, a simple business model in which parties manually accept, or
|
||
reject each other’s trade proposals which is implemented in
|
||
<code class="docutils literal"><span class="pre">WorkflowTransactionBuildTutorial.kt</span></code>. To run and explore these
|
||
examples using the IntelliJ IDE one can run/step the respective unit
|
||
tests in <code class="docutils literal"><span class="pre">FxTransactionBuildTutorialTest.kt</span></code> and
|
||
<code class="docutils literal"><span class="pre">WorkflowTransactionBuildTutorialTest.kt</span></code>, which drive the flows as
|
||
part of a simulated in-memory network of nodes. When creating the
|
||
IntelliJ run configuration for these unit test set the workspace
|
||
points to the root <code class="docutils literal"><span class="pre">r3prototyping</span></code> folder and add
|
||
<code class="docutils literal"><span class="pre">-javaagent:lib/quasar.jar</span></code> to the VM options, so that the <code class="docutils literal"><span class="pre">Quasar</span></code>
|
||
instrumentation is correctly configured.</p>
|
||
<p>For the Cash transaction let’s assume the cash resources are using the
|
||
standard <code class="docutils literal"><span class="pre">CashState</span></code> in the <code class="docutils literal"><span class="pre">:financial</span></code> Gradle module. The Cash
|
||
contract uses <code class="docutils literal"><span class="pre">FungibleAsset</span></code> states to model holdings of
|
||
interchangeable assets and allow the split/merge and summing of
|
||
states to meet a contractual obligation. We would normally use the
|
||
<code class="docutils literal"><span class="pre">generateSpend</span></code> method on the <code class="docutils literal"><span class="pre">VaultService</span></code> to gather the required
|
||
amount of cash into a <code class="docutils literal"><span class="pre">TransactionBuilder</span></code>, set the outputs and move
|
||
command. However, to elucidate more clearly example flow code is shown
|
||
here that will manually carry out the inputs queries using the lower
|
||
level <code class="docutils literal"><span class="pre">VaultService</span></code>.</p>
|
||
<div class="highlight-kotlin"><div class="highlight"><pre><span></span><span class="c1">// This is equivalent to the VaultService.generateSpend</span>
|
||
<span class="c1">// Which is brought here to make the filtering logic more visible in the example</span>
|
||
<span class="k">private</span> <span class="k">fun</span> <span class="nf">gatherOurInputs</span><span class="p">(</span><span class="n">serviceHub</span><span class="p">:</span> <span class="n">ServiceHub</span><span class="p">,</span>
|
||
<span class="n">amountRequired</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">notary</span><span class="p">:</span> <span class="n">Party</span><span class="p">?):</span> <span class="n">Pair</span><span class="p"><</span><span class="n">List</span><span class="p"><</span><span class="n">StateAndRef</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">Long</span><span class="p">></span> <span class="p">{</span>
|
||
<span class="c1">// Collect cash type inputs</span>
|
||
<span class="k">val</span> <span class="py">cashStates</span> <span class="p">=</span> <span class="n">serviceHub</span><span class="p">.</span><span class="n">vaultService</span><span class="p">.</span><span class="n">currentVault</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="c1">// extract our key identity for convenience</span>
|
||
<span class="k">val</span> <span class="py">ourKey</span> <span class="p">=</span> <span class="n">serviceHub</span><span class="p">.</span><span class="n">myInfo</span><span class="p">.</span><span class="n">legalIdentity</span><span class="p">.</span><span class="n">owningKey</span>
|
||
<span class="c1">// Filter down to our own cash states with right currency and issuer</span>
|
||
<span class="k">val</span> <span class="py">suitableCashStates</span> <span class="p">=</span> <span class="n">cashStates</span><span class="p">.</span><span class="n">filter</span> <span class="p">{</span>
|
||
<span class="k">val</span> <span class="py">state</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="k">data</span>
|
||
<span class="p">(</span><span class="n">state</span><span class="p">.</span><span class="n">owner</span> <span class="p">==</span> <span class="n">ourKey</span><span class="p">)</span>
|
||
<span class="p">&&</span> <span class="p">(</span><span class="n">state</span><span class="p">.</span><span class="n">amount</span><span class="p">.</span><span class="n">token</span> <span class="p">==</span> <span class="n">amountRequired</span><span class="p">.</span><span class="n">token</span><span class="p">)</span>
|
||
<span class="p">}</span>
|
||
<span class="n">require</span><span class="p">(!</span><span class="n">suitableCashStates</span><span class="p">.</span><span class="n">isEmpty</span><span class="p">())</span> <span class="p">{</span> <span class="s">"Insufficient funds"</span> <span class="p">}</span>
|
||
<span class="k">var</span> <span class="py">remaining</span> <span class="p">=</span> <span class="n">amountRequired</span><span class="p">.</span><span class="n">quantity</span>
|
||
<span class="c1">// We will need all of the inputs to be on the same notary.</span>
|
||
<span class="c1">// For simplicity we just filter on the first notary encountered</span>
|
||
<span class="c1">// A production quality flow would need to migrate notary if the</span>
|
||
<span class="c1">// the amounts were not sufficient in any one notary</span>
|
||
<span class="k">val</span> <span class="py">sourceNotary</span><span class="p">:</span> <span class="n">Party</span> <span class="p">=</span> <span class="n">notary</span> <span class="o">?:</span> <span class="n">suitableCashStates</span><span class="p">.</span><span class="n">first</span><span class="p">().</span><span class="n">state</span><span class="p">.</span><span class="n">notary</span>
|
||
|
||
<span class="k">val</span> <span class="py">inputsList</span> <span class="p">=</span> <span class="n">mutableListOf</span><span class="p"><</span><span class="n">StateAndRef</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="c1">// Iterate over filtered cash states to gather enough to pay</span>
|
||
<span class="k">for</span> <span class="p">(</span><span class="n">cash</span> <span class="k">in</span> <span class="n">suitableCashStates</span><span class="p">.</span><span class="n">filter</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">notary</span> <span class="p">==</span> <span class="n">sourceNotary</span> <span class="p">})</span> <span class="p">{</span>
|
||
<span class="n">inputsList</span> <span class="p">+=</span> <span class="n">cash</span>
|
||
<span class="k">if</span> <span class="p">(</span><span class="n">remaining</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="k">data</span><span class="p">.</span><span class="n">amount</span><span class="p">.</span><span class="n">quantity</span><span class="p">)</span> <span class="p">{</span>
|
||
<span class="k">return</span> <span class="n">Pair</span><span class="p">(</span><span class="n">inputsList</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="k">data</span><span class="p">.</span><span class="n">amount</span><span class="p">.</span><span class="n">quantity</span> <span class="p">-</span> <span class="n">remaining</span><span class="p">)</span>
|
||
<span class="p">}</span>
|
||
<span class="n">remaining</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="k">data</span><span class="p">.</span><span class="n">amount</span><span class="p">.</span><span class="n">quantity</span>
|
||
<span class="p">}</span>
|
||
<span class="k">throw</span> <span class="n">IllegalStateException</span><span class="p">(</span><span class="s">"Insufficient funds"</span><span class="p">)</span>
|
||
<span class="p">}</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>As a foreign exchange transaction we expect an exchange of two
|
||
currencies, so we will also require a set of input states from the other
|
||
counterparty. However, the Corda privacy model means we do not know the
|
||
other node’s states. Our flow must therefore negotiate with the other
|
||
node for them to carry out a similar query and populate the inputs (See
|
||
the <code class="docutils literal"><span class="pre">ForeignExchangeFlow</span></code> for more details of the exchange). Having
|
||
identified a set of Input <code class="docutils literal"><span class="pre">StateRef</span></code> items we can then create the
|
||
output as discussed below.</p>
|
||
<p>For the trade approval flow we need to implement a simple workflow
|
||
pattern. We start by recording the unconfirmed trade details in a state
|
||
object implementing the <code class="docutils literal"><span class="pre">LinearState</span></code> interface. One field of this
|
||
record is used to map the business workflow to an enumerated state.
|
||
Initially the initiator creates a new state object which receives a new
|
||
<code class="docutils literal"><span class="pre">UniqueIdentifier</span></code> in its <code class="docutils literal"><span class="pre">linearId</span></code> property and a starting
|
||
workflow state of <code class="docutils literal"><span class="pre">NEW</span></code>. The <code class="docutils literal"><span class="pre">Contract.verify</span></code> method is written to
|
||
allow the initiator to sign this initial transaction and send it to the
|
||
other party. This pattern ensures that a permanent copy is recorded on
|
||
both ledgers for audit purposes, but the state is prevented from being
|
||
maliciously put in an approved state. The subsequent workflow steps then
|
||
follow with transactions that consume the state as inputs on one side
|
||
and output a new version with whatever state updates, or amendments
|
||
match to the business process, the <code class="docutils literal"><span class="pre">linearId</span></code> being preserved across
|
||
the changes. Attached <code class="docutils literal"><span class="pre">Command</span></code> objects help the verify method
|
||
restrict changes to appropriate fields and signers at each step in the
|
||
workflow. In this it is typical to have both parties sign the change
|
||
transactions, but it can be valid to allow unilateral signing, if for instance
|
||
one side could block a rejection. Commonly the manual initiator of these
|
||
workflows will query the Vault for states of the right contract type and
|
||
in the right workflow state over the RPC interface. The RPC will then
|
||
initiate the relevant flow using <code class="docutils literal"><span class="pre">StateRef</span></code>, or <code class="docutils literal"><span class="pre">linearId</span></code> values as
|
||
parameters to the flow to identify the states being operated upon. Thus
|
||
code to gather the latest input state would be:</p>
|
||
<div class="highlight-kotlin"><div class="highlight"><pre><span></span>
|
||
// Helper method to locate the latest Vault version of a LinearState from a possibly out of date StateRef
|
||
inline fun <reified T : LinearState> ServiceHub.latest(ref: StateRef): StateAndRef<T> {
|
||
val linearHeads = vaultService.linearHeadsOfType<T>()
|
||
val original = toStateAndRef<T>(ref)
|
||
return linearHeads.get(original.state.data.linearId)!!
|
||
}
|
||
</pre></div>
|
||
</div>
|
||
<div class="codeset container">
|
||
<div class="highlight-kotlin"><div class="highlight"><pre><span></span><span class="c1">// Pull in the latest Vault version of the StateRef as a full StateAndRef</span>
|
||
<span class="k">val</span> <span class="py">latestRecord</span> <span class="p">=</span> <span class="n">serviceHub</span><span class="p">.</span><span class="n">latest</span><span class="p"><</span><span class="n">TradeApprovalContract</span><span class="p">.</span><span class="n">State</span><span class="p">>(</span><span class="n">ref</span><span class="p">)</span>
|
||
</pre></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="section" id="generating-commands">
|
||
<h2>Generating Commands<a class="headerlink" href="#generating-commands" title="Permalink to this headline">¶</a></h2>
|
||
<p>For the commands that will be added to the transaction, these will need
|
||
to correctly reflect the task at hand. These must match because inside
|
||
the <code class="docutils literal"><span class="pre">Contract.verify</span></code> method the command will be used to select the
|
||
validation code path. The <code class="docutils literal"><span class="pre">Contract.verify</span></code> method will then restrict
|
||
the allowed contents of the transaction to reflect this context. Typical
|
||
restrictions might include that the input cash amount must equal the
|
||
output cash amount, or that a workflow step is only allowed to change
|
||
the status field. Sometimes, the command may capture some data too e.g.
|
||
the foreign exchange rate, or the identity of one party, or the StateRef
|
||
of the specific input that originates the command in a bulk operation.
|
||
This data will be used to further aid the <code class="docutils literal"><span class="pre">Contract.verify</span></code>, because
|
||
to ensure consistent, secure and reproducible behaviour in a distributed
|
||
environment the <code class="docutils literal"><span class="pre">Contract.verify</span></code>, transaction is the only allowed to
|
||
use the content of the transaction to decide validity.</p>
|
||
<p>Another essential requirement for commands is that the correct set of
|
||
<code class="docutils literal"><span class="pre">CompositeKeys</span></code> are added to the Command on the builder, which will be
|
||
used to form the set of required signers on the final validated
|
||
transaction. These must correctly align with the expectations of the
|
||
<code class="docutils literal"><span class="pre">Contract.verify</span></code> method, which should be written to defensively check
|
||
this. In particular, it is expected that at minimum the owner of an
|
||
asset would have to be signing to permission transfer of that asset. In
|
||
addition, other signatories will often be required e.g. an Oracle
|
||
identity for an Oracle command, or both parties when there is an
|
||
exchange of assets.</p>
|
||
</div>
|
||
<div class="section" id="generating-outputs">
|
||
<h2>Generating Outputs<a class="headerlink" href="#generating-outputs" title="Permalink to this headline">¶</a></h2>
|
||
<p>Having located a set of <code class="docutils literal"><span class="pre">StateAndRefs</span></code> as the transaction inputs, the
|
||
flow has to generate the output states. Typically, this is a simple call
|
||
to the Kotlin <code class="docutils literal"><span class="pre">copy</span></code> method to modify the few fields that will
|
||
transitioned in the transaction. The contract code may provide a
|
||
<code class="docutils literal"><span class="pre">generateXXX</span></code> method to help with this process if the task is more
|
||
complicated. With a workflow state a slightly modified copy state is
|
||
usually sufficient, especially as it is expected that we wish to preserve
|
||
the <code class="docutils literal"><span class="pre">linearId</span></code> between state revisions, so that Vault queries can find
|
||
the latest revision.</p>
|
||
<p>For fungible contract states such as <code class="docutils literal"><span class="pre">Cash</span></code> it is common to distribute
|
||
and split the total amount e.g. to produce a remaining balance output
|
||
state for the original owner when breaking up a large amount input
|
||
state. Remember that the result of a successful transaction is always to
|
||
fully consume/spend the input states, so this is required to conserve
|
||
the total cash. For example from the demo code:</p>
|
||
<div class="highlight-kotlin"><div class="highlight"><pre><span></span> // Gather our inputs. We would normally use VaultService.generateSpend
|
||
// to carry out the build in a single step. To be more explicit
|
||
// we will use query manually in the helper function below.
|
||
// Putting this into a non-suspendable function also prevents issues when
|
||
// the flow is suspended.
|
||
val (inputs, residual) = gatherOurInputs(serviceHub, sellAmount, request.notary)
|
||
|
||
// Build and an output state for the counterparty
|
||
val transferedFundsOutput = Cash.State(sellAmount, request.counterparty.owningKey, null)
|
||
|
||
if (residual > 0L) {
|
||
// Build an output state for the residual change back to us
|
||
val residualAmount = Amount(residual, sellAmount.token)
|
||
val residualOutput = Cash.State(residualAmount, serviceHub.myInfo.legalIdentity.owningKey, null)
|
||
return FxResponse(inputs, listOf(transferedFundsOutput, residualOutput))
|
||
} else {
|
||
return FxResponse(inputs, listOf(transferedFundsOutput))
|
||
}
|
||
</pre></div>
|
||
</div>
|
||
</div>
|
||
<div class="section" id="building-the-wiretransaction">
|
||
<h2>Building the WireTransaction<a class="headerlink" href="#building-the-wiretransaction" title="Permalink to this headline">¶</a></h2>
|
||
<p>Having gathered all the ingredients for the transaction we now need to
|
||
use a <code class="docutils literal"><span class="pre">TransactionBuilder</span></code> to construct the full <code class="docutils literal"><span class="pre">WireTransaction</span></code>.
|
||
The initial <code class="docutils literal"><span class="pre">TransactionBuilder</span></code> should be created by calling the
|
||
<code class="docutils literal"><span class="pre">TransactionType.General.Builder</span></code> method. (The other
|
||
<code class="docutils literal"><span class="pre">TransactionBuilder</span></code> implementation is only used for the <code class="docutils literal"><span class="pre">NotaryChange</span></code> flow where
|
||
<code class="docutils literal"><span class="pre">ContractStates</span></code> need moving to a different Notary.) At this point the
|
||
Notary to associate with the states should be recorded. Then we keep
|
||
adding inputs, outputs, commands and attachments to fill the
|
||
transaction. Examples of this process are:</p>
|
||
<div class="highlight-kotlin"><div class="highlight"><pre><span></span> <span class="c1">// Modify the state field for new output. We use copy, to ensure no other modifications.</span>
|
||
<span class="c1">// It is especially important for a LinearState that the linearId is copied across,</span>
|
||
<span class="c1">// not accidentally assigned a new random id.</span>
|
||
<span class="k">val</span> <span class="py">newState</span> <span class="p">=</span> <span class="n">latestRecord</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">copy</span><span class="p">(</span><span class="n">state</span> <span class="p">=</span> <span class="n">verdict</span><span class="p">)</span>
|
||
|
||
<span class="c1">// We have to use the original notary for the new transaction</span>
|
||
<span class="k">val</span> <span class="py">notary</span> <span class="p">=</span> <span class="n">latestRecord</span><span class="p">.</span><span class="n">state</span><span class="p">.</span><span class="n">notary</span>
|
||
|
||
<span class="c1">// Get and populate the new TransactionBuilder</span>
|
||
<span class="c1">// To destroy the old proposal state and replace with the new completion state.</span>
|
||
<span class="c1">// Also add the Completed command with keys of all parties to signal the Tx purpose</span>
|
||
<span class="c1">// to the Contract verify method.</span>
|
||
<span class="k">val</span> <span class="py">tx</span> <span class="p">=</span> <span class="n">TransactionType</span><span class="p">.</span>
|
||
<span class="n">General</span><span class="p">.</span>
|
||
<span class="n">Builder</span><span class="p">(</span><span class="n">notary</span><span class="p">).</span>
|
||
<span class="n">withItems</span><span class="p">(</span>
|
||
<span class="n">latestRecord</span><span class="p">,</span>
|
||
<span class="n">newState</span><span class="p">,</span>
|
||
<span class="n">Command</span><span class="p">(</span><span class="n">TradeApprovalContract</span><span class="p">.</span><span class="n">Commands</span><span class="p">.</span><span class="n">Completed</span><span class="p">(),</span>
|
||
<span class="n">listOf</span><span class="p">(</span><span class="n">serviceHub</span><span class="p">.</span><span class="n">myInfo</span><span class="p">.</span><span class="n">legalIdentity</span><span class="p">.</span><span class="n">owningKey</span><span class="p">,</span> <span class="n">latestRecord</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">source</span><span class="p">.</span><span class="n">owningKey</span><span class="p">)))</span>
|
||
<span class="n">tx</span><span class="p">.</span><span class="n">setTime</span><span class="p">(</span><span class="n">serviceHub</span><span class="p">.</span><span class="n">clock</span><span class="p">.</span><span class="n">instant</span><span class="p">(),</span> <span class="n">Duration</span><span class="p">.</span><span class="n">ofSeconds</span><span class="p">(</span><span class="m">60</span><span class="p">))</span>
|
||
<span class="c1">// We can sign this transaction immediately as we have already checked all the fields and the decision</span>
|
||
<span class="c1">// is ultimately a manual one from the caller.</span>
|
||
<span class="n">tx</span><span class="p">.</span><span class="n">signWith</span><span class="p">(</span><span class="n">serviceHub</span><span class="p">.</span><span class="n">legalIdentityKey</span><span class="p">)</span>
|
||
<span class="c1">// Convert to SignedTransaction we can pass around certain that it cannot be modified.</span>
|
||
<span class="k">val</span> <span class="py">selfSignedTx</span> <span class="p">=</span> <span class="n">tx</span><span class="p">.</span><span class="n">toSignedTransaction</span><span class="p">(</span><span class="k">false</span><span class="p">)</span>
|
||
</pre></div>
|
||
</div>
|
||
<div class="highlight-kotlin"><div class="highlight"><pre><span></span> <span class="k">private</span> <span class="k">fun</span> <span class="nf">buildTradeProposal</span><span class="p">(</span><span class="n">ourStates</span><span class="p">:</span> <span class="n">FxResponse</span><span class="p">,</span> <span class="n">theirStates</span><span class="p">:</span> <span class="n">FxResponse</span><span class="p">):</span> <span class="n">SignedTransaction</span> <span class="p">{</span>
|
||
<span class="c1">// This is the correct way to create a TransactionBuilder,</span>
|
||
<span class="c1">// do not construct directly.</span>
|
||
<span class="c1">// We also set the notary to match the input notary</span>
|
||
<span class="k">val</span> <span class="py">builder</span> <span class="p">=</span> <span class="n">TransactionType</span><span class="p">.</span><span class="n">General</span><span class="p">.</span><span class="n">Builder</span><span class="p">(</span><span class="n">ourStates</span><span class="p">.</span><span class="n">inputs</span><span class="p">.</span><span class="n">first</span><span class="p">().</span><span class="n">state</span><span class="p">.</span><span class="n">notary</span><span class="p">)</span>
|
||
|
||
<span class="c1">// Add the move commands and key to indicate all the respective owners and need to sign</span>
|
||
<span class="k">val</span> <span class="py">ourSigners</span> <span class="p">=</span> <span class="n">ourStates</span><span class="p">.</span><span class="n">inputs</span><span class="p">.</span><span class="n">map</span> <span class="p">{</span> <span class="n">it</span><span class="p">.</span><span class="n">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">toSet</span><span class="p">()</span>
|
||
<span class="k">val</span> <span class="py">theirSigners</span> <span class="p">=</span> <span class="n">theirStates</span><span class="p">.</span><span class="n">inputs</span><span class="p">.</span><span class="n">map</span> <span class="p">{</span> <span class="n">it</span><span class="p">.</span><span class="n">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">toSet</span><span class="p">()</span>
|
||
<span class="n">builder</span><span class="p">.</span><span class="n">addCommand</span><span class="p">(</span><span class="n">Cash</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="p">(</span><span class="n">ourSigners</span> <span class="p">+</span> <span class="n">theirSigners</span><span class="p">).</span><span class="n">toList</span><span class="p">())</span>
|
||
|
||
<span class="c1">// Build and add the inputs and outputs</span>
|
||
<span class="n">builder</span><span class="p">.</span><span class="n">withItems</span><span class="p">(*</span><span class="n">ourStates</span><span class="p">.</span><span class="n">inputs</span><span class="p">.</span><span class="n">toTypedArray</span><span class="p">())</span>
|
||
<span class="n">builder</span><span class="p">.</span><span class="n">withItems</span><span class="p">(*</span><span class="n">theirStates</span><span class="p">.</span><span class="n">inputs</span><span class="p">.</span><span class="n">toTypedArray</span><span class="p">())</span>
|
||
<span class="n">builder</span><span class="p">.</span><span class="n">withItems</span><span class="p">(*</span><span class="n">ourStates</span><span class="p">.</span><span class="n">outputs</span><span class="p">.</span><span class="n">toTypedArray</span><span class="p">())</span>
|
||
<span class="n">builder</span><span class="p">.</span><span class="n">withItems</span><span class="p">(*</span><span class="n">theirStates</span><span class="p">.</span><span class="n">outputs</span><span class="p">.</span><span class="n">toTypedArray</span><span class="p">())</span>
|
||
|
||
<span class="c1">// We have already validated their response and trust our own data</span>
|
||
<span class="c1">// so we can sign</span>
|
||
<span class="n">builder</span><span class="p">.</span><span class="n">signWith</span><span class="p">(</span><span class="n">serviceHub</span><span class="p">.</span><span class="n">legalIdentityKey</span><span class="p">)</span>
|
||
<span class="c1">// create a signed transaction, but pass false as parameter, because we know it is not fully signed</span>
|
||
<span class="k">val</span> <span class="py">signedTransaction</span> <span class="p">=</span> <span class="n">builder</span><span class="p">.</span><span class="n">toSignedTransaction</span><span class="p">(</span><span class="n">checkSufficientSignatures</span> <span class="p">=</span> <span class="k">false</span><span class="p">)</span>
|
||
<span class="k">return</span> <span class="n">signedTransaction</span>
|
||
<span class="p">}</span>
|
||
</pre></div>
|
||
</div>
|
||
</div>
|
||
<div class="section" id="completing-the-signedtransaction">
|
||
<h2>Completing the SignedTransaction<a class="headerlink" href="#completing-the-signedtransaction" title="Permalink to this headline">¶</a></h2>
|
||
<p>Having created an initial <code class="docutils literal"><span class="pre">WireTransaction</span></code> and converted this to an
|
||
initial <code class="docutils literal"><span class="pre">SignedTransaction</span></code> the process of verifying and forming a
|
||
full <code class="docutils literal"><span class="pre">SignedTransaction</span></code> begins and then completes with the
|
||
notarisation. In practice this is a relatively stereotypical process,
|
||
because assuming the <code class="docutils literal"><span class="pre">WireTransaction</span></code> is correctly constructed the
|
||
verification should be immediate. However, it is also important to
|
||
recheck the business details of any data received back from an external
|
||
node, because a malicious party could always modify the contents before
|
||
returning the transaction. Each remote flow should therefore check as
|
||
much as possible of the initial <code class="docutils literal"><span class="pre">SignedTransaction</span></code> inside the <code class="docutils literal"><span class="pre">unwrap</span></code> of
|
||
the receive before agreeing to sign. Any issues should immediately throw
|
||
an exception to abort the flow. Similarly the originator, should always
|
||
apply any new signatures to its original proposal to ensure the contents
|
||
of the transaction has not been altered by the remote parties.</p>
|
||
<p>The typical code therefore checks the received <code class="docutils literal"><span class="pre">SignedTransaction</span></code>
|
||
using the <code class="docutils literal"><span class="pre">verifySignatures</span></code> method, but excluding itself, the notary
|
||
and any other parties yet to apply their signature. The contents of the
|
||
<code class="docutils literal"><span class="pre">WireTransaction</span></code> inside the <code class="docutils literal"><span class="pre">SignedTransaction</span></code> should be fully
|
||
verified further by expanding with <code class="docutils literal"><span class="pre">toLedgerTransaction</span></code> and calling
|
||
<code class="docutils literal"><span class="pre">verify</span></code>. Further context specific and business checks should then be
|
||
made, because the <code class="docutils literal"><span class="pre">Contract.verify</span></code> is not allowed to access external
|
||
context. For example the flow may need to check that the parties are the
|
||
right ones, or that the <code class="docutils literal"><span class="pre">Command</span></code> present on the transaction is as
|
||
expected for this specific flow. An example of this from the demo code is:</p>
|
||
<div class="highlight-kotlin"><div class="highlight"><pre><span></span> <span class="c1">// First we receive the verdict transaction signed by their single key</span>
|
||
<span class="k">val</span> <span class="py">completeTx</span> <span class="p">=</span> <span class="n">receive</span><span class="p"><</span><span class="n">SignedTransaction</span><span class="p">>(</span><span class="n">source</span><span class="p">).</span><span class="n">unwrap</span> <span class="p">{</span>
|
||
<span class="c1">// Check the transaction is signed apart from our own key and the notary</span>
|
||
<span class="k">val</span> <span class="py">wtx</span> <span class="p">=</span> <span class="n">it</span><span class="p">.</span><span class="n">verifySignatures</span><span class="p">(</span><span class="n">serviceHub</span><span class="p">.</span><span class="n">myInfo</span><span class="p">.</span><span class="n">legalIdentity</span><span class="p">.</span><span class="n">owningKey</span><span class="p">,</span> <span class="n">it</span><span class="p">.</span><span class="n">tx</span><span class="p">.</span><span class="n">notary</span><span class="o">!!</span><span class="p">.</span><span class="n">owningKey</span><span class="p">)</span>
|
||
<span class="c1">// Check the transaction data is correctly formed</span>
|
||
<span class="n">wtx</span><span class="p">.</span><span class="n">toLedgerTransaction</span><span class="p">(</span><span class="n">serviceHub</span><span class="p">).</span><span class="n">verify</span><span class="p">()</span>
|
||
<span class="c1">// Confirm that this is the expected type of transaction</span>
|
||
<span class="n">require</span><span class="p">(</span><span class="n">wtx</span><span class="p">.</span><span class="n">commands</span><span class="p">.</span><span class="n">single</span><span class="p">().</span><span class="n">value</span> <span class="k">is</span> <span class="n">TradeApprovalContract</span><span class="p">.</span><span class="n">Commands</span><span class="p">.</span><span class="n">Completed</span><span class="p">)</span> <span class="p">{</span>
|
||
<span class="s">"Transaction must represent a workflow completion"</span>
|
||
<span class="p">}</span>
|
||
<span class="c1">// Check the context dependent parts of the transaction as the</span>
|
||
<span class="c1">// Contract verify method must not use serviceHub queries.</span>
|
||
<span class="k">val</span> <span class="py">state</span> <span class="p">=</span> <span class="n">wtx</span><span class="p">.</span><span class="n">outRef</span><span class="p"><</span><span class="n">TradeApprovalContract</span><span class="p">.</span><span class="n">State</span><span class="p">>(</span><span class="m">0</span><span class="p">)</span>
|
||
<span class="n">require</span><span class="p">(</span><span class="n">state</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">source</span> <span class="p">==</span> <span class="n">serviceHub</span><span class="p">.</span><span class="n">myInfo</span><span class="p">.</span><span class="n">legalIdentity</span><span class="p">)</span> <span class="p">{</span>
|
||
<span class="s">"Proposal not one of our original proposals"</span>
|
||
<span class="p">}</span>
|
||
<span class="n">require</span><span class="p">(</span><span class="n">state</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">counterparty</span> <span class="p">==</span> <span class="n">source</span><span class="p">)</span> <span class="p">{</span>
|
||
<span class="s">"Proposal not for sent from correct source"</span>
|
||
<span class="p">}</span>
|
||
<span class="n">it</span>
|
||
<span class="p">}</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>After verification the remote flow will return its signature to the
|
||
originator. The originator should apply that signature to the starting
|
||
<code class="docutils literal"><span class="pre">SignedTransaction</span></code> and recheck the signatures match.</p>
|
||
</div>
|
||
<div class="section" id="committing-the-transaction">
|
||
<h2>Committing the Transaction<a class="headerlink" href="#committing-the-transaction" title="Permalink to this headline">¶</a></h2>
|
||
<p>Once all the party signatures are applied to the SignedTransaction the
|
||
final step is notarisation. This involves calling <code class="docutils literal"><span class="pre">NotaryFlow.Client</span></code>
|
||
to confirm the transaction, consume the inputs and return its confirming
|
||
signature. Then the flow should ensure that all nodes end with all
|
||
signatures and that they call <code class="docutils literal"><span class="pre">ServiceHub.recordTransactions</span></code>. The
|
||
code for this is standardised in the <code class="docutils literal"><span class="pre">FinalityFlow</span></code>, or more explictly
|
||
an example is:</p>
|
||
<div class="highlight-kotlin"><div class="highlight"><pre><span></span> <span class="c1">// Run the FinalityFlow to notarise and distribute the completed transaction.</span>
|
||
<span class="n">subFlow</span><span class="p">(</span><span class="n">FinalityFlow</span><span class="p">(</span><span class="n">allPartySignedTx</span><span class="p">,</span>
|
||
<span class="n">setOf</span><span class="p">(</span><span class="n">latestRecord</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">source</span><span class="p">,</span> <span class="n">latestRecord</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">counterparty</span><span class="p">)))</span>
|
||
</pre></div>
|
||
</div>
|
||
</div>
|
||
<div class="section" id="partially-visible-transactions">
|
||
<h2>Partially Visible Transactions<a class="headerlink" href="#partially-visible-transactions" title="Permalink to this headline">¶</a></h2>
|
||
<p>The discussion so far has assumed that the parties need full visibility
|
||
of the transaction to sign. However, there may be situations where each
|
||
party needs to store private data for audit purposes, or for evidence to
|
||
a regulator, but does not wish to share that with the other trading
|
||
partner. The tear-off/Merkle tree support in Corda allows flows to send
|
||
portions of the full transaction to restrict visibility to remote
|
||
parties. To do this one can use the
|
||
<code class="docutils literal"><span class="pre">WireTransaction.buildFilteredTransaction</span></code> extension method to produce
|
||
a <code class="docutils literal"><span class="pre">FilteredTransaction</span></code>. The elements of the <code class="docutils literal"><span class="pre">SignedTransaction</span></code>
|
||
which we wish to be hide will be replaced with their secure hash. The
|
||
overall transaction txid is still provable from the
|
||
<code class="docutils literal"><span class="pre">FilteredTransaction</span></code> preventing change of the private data, but we do
|
||
not expose that data to the other node directly. A full example of this
|
||
can be found in the <code class="docutils literal"><span class="pre">NodeInterestRates</span></code> Oracle code from the
|
||
<code class="docutils literal"><span class="pre">irs-demo</span></code> project which interacts with the <code class="docutils literal"><span class="pre">RatesFixFlow</span></code> flow.
|
||
Also, refer to the <a class="reference internal" href="merkle-trees.html"><span class="doc">Transaction tear-offs</span></a> documentation.</p>
|
||
</div>
|
||
</div>
|
||
|
||
|
||
</div>
|
||
</div>
|
||
<footer>
|
||
|
||
<div class="rst-footer-buttons" role="navigation" aria-label="footer navigation">
|
||
|
||
<a href="flow-state-machines.html" class="btn btn-neutral float-right" title="Writing flows" accesskey="n">Next <span class="fa fa-arrow-circle-right"></span></a>
|
||
|
||
|
||
<a href="tutorial-clientrpc-api.html" class="btn btn-neutral" title="Client RPC API tutorial" accesskey="p"><span class="fa fa-arrow-circle-left"></span> Previous</a>
|
||
|
||
</div>
|
||
|
||
|
||
<hr/>
|
||
|
||
<div role="contentinfo">
|
||
<p>
|
||
© Copyright 2016, R3 Limited.
|
||
|
||
</p>
|
||
</div>
|
||
Built with <a href="http://sphinx-doc.org/">Sphinx</a> using a <a href="https://github.com/snide/sphinx_rtd_theme">theme</a> provided by <a href="https://readthedocs.org">Read the Docs</a>.
|
||
|
||
</footer>
|
||
|
||
</div>
|
||
</div>
|
||
|
||
</section>
|
||
|
||
</div>
|
||
|
||
|
||
|
||
|
||
|
||
<script type="text/javascript">
|
||
var DOCUMENTATION_OPTIONS = {
|
||
URL_ROOT:'./',
|
||
VERSION:'latest',
|
||
COLLAPSE_INDEX:false,
|
||
FILE_SUFFIX:'.html',
|
||
HAS_SOURCE: true
|
||
};
|
||
</script>
|
||
<script type="text/javascript" src="_static/jquery.js"></script>
|
||
<script type="text/javascript" src="_static/underscore.js"></script>
|
||
<script type="text/javascript" src="_static/doctools.js"></script>
|
||
|
||
|
||
|
||
|
||
|
||
<script type="text/javascript" src="_static/js/theme.js"></script>
|
||
|
||
|
||
|
||
|
||
<script type="text/javascript">
|
||
jQuery(function () {
|
||
SphinxRtdTheme.StickyNav.enable();
|
||
});
|
||
</script>
|
||
|
||
|
||
</body>
|
||
</html> |