2017-01-03 13:07:48 +00:00
<!-- If you edit this, then please make the same changes to layout_for_doc_website.html, as that is used for the web
doc site generation which we put analytics tracking on to identify any potential problem pages -->
2016-11-11 11:52:29 +00:00
<!DOCTYPE html>
<!-- [if IE 8]><html class="no - js lt - ie9" lang="en" > <![endif] -->
<!-- [if gt IE 8]><! --> < html class = "no-js" lang = "en" > <!-- <![endif] -->
< head >
< meta charset = "utf-8" >
< meta name = "viewport" content = "width=device-width, initial-scale=1.0" >
2016-11-29 11:38:52 +00:00
< title > Client RPC API tutorial — R3 Corda latest documentation< / title >
2016-11-11 11:52:29 +00:00
< link rel = "stylesheet" href = "_static/css/custom.css" type = "text/css" / >
2017-02-08 16:08:46 +00:00
< link rel = "index" title = "Index"
href="genindex.html"/>
< link rel = "search" title = "Search" href = "search.html" / >
2016-11-11 11:52:29 +00:00
< link rel = "top" title = "R3 Corda latest documentation" href = "index.html" / >
2017-01-06 17:38:23 +00:00
< link rel = "next" title = "Building transactions" href = "tutorial-building-transactions.html" / >
< link rel = "prev" title = "Integration testing" href = "tutorial-integration-testing.html" / >
2016-11-11 11:52:29 +00:00
< script src = "_static/js/modernizr.min.js" > < / script >
< / head >
< body class = "wy-body-for-nav" role = "document" >
< div class = "wy-grid-for-nav" >
< nav data-toggle = "wy-nav-shift" class = "wy-nav-side" >
< div class = "wy-side-scroll" >
< div class = "wy-side-nav-search" >
< 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 >
2017-01-19 17:11:18 +00:00
API reference: < a href = "api/kotlin/corda/index.html" > Kotlin< / a > / < a href = "api/javadoc/index.html" > JavaDoc< / a >
2017-01-03 13:07:48 +00:00
< br >
< a href = "https://discourse.corda.net" > Discourse Forums< / a >
< br >
< a href = "http://slack.corda.net" > Slack< / a >
< br >
2016-11-11 11:52:29 +00:00
< / div >
< div class = "wy-menu wy-menu-vertical" data-spy = "affix" role = "navigation" aria-label = "main navigation" >
2016-11-23 12:50:02 +00:00
< p class = "caption" > < span class = "caption-text" > Getting started< / span > < / p >
2016-11-11 11:52:29 +00:00
< 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 >
2017-01-06 17:38:23 +00:00
< li class = "toctree-l1" > < a class = "reference internal" href = "getting-set-up-fault-finding.html" > Troubleshooting< / a > < / li >
2016-11-23 12:50:02 +00:00
< li class = "toctree-l1" > < a class = "reference internal" href = "running-the-demos.html" > Running the demos< / a > < / li >
2016-11-29 18:44:59 +00:00
< li class = "toctree-l1" > < a class = "reference internal" href = "CLI-vs-IDE.html" > CLI vs IDE< / a > < / li >
2016-11-23 12:50:02 +00:00
< / ul >
< p class = "caption" > < span class = "caption-text" > Key concepts< / span > < / p >
< ul >
2017-01-26 16:57:23 +00:00
< li class = "toctree-l1" > < a class = "reference internal" href = "key-concepts.html" > Overview< / a > < / li >
< li class = "toctree-l1" > < a class = "reference internal" href = "key-concepts-ecosystem.html" > Corda ecosystem< / a > < / li >
< li class = "toctree-l1" > < a class = "reference internal" href = "key-concepts-data-model.html" > Data model< / a > < / li >
< li class = "toctree-l1" > < a class = "reference internal" href = "key-concepts-core-types.html" > Core types< / a > < / li >
< li class = "toctree-l1" > < a class = "reference internal" href = "key-concepts-financial-model.html" > Financial model< / a > < / li >
< li class = "toctree-l1" > < a class = "reference internal" href = "key-concepts-flow-framework.html" > Flow framework< / a > < / li >
< li class = "toctree-l1" > < a class = "reference internal" href = "key-concepts-consensus-notaries.html" > Consensus and notaries< / a > < / li >
< li class = "toctree-l1" > < a class = "reference internal" href = "key-concepts-vault.html" > Vault< / a > < / li >
< li class = "toctree-l1" > < a class = "reference internal" href = "key-concepts-security-model.html" > Security model< / a > < / li >
2016-11-29 18:44:59 +00:00
< / ul >
< p class = "caption" > < span class = "caption-text" > CorDapps< / span > < / p >
< ul >
2017-01-06 17:38:23 +00:00
< li class = "toctree-l1" > < a class = "reference internal" href = "creating-a-cordapp.html" > CorDapp basics< / a > < / li >
2017-02-08 16:08:46 +00:00
< li class = "toctree-l1" > < a class = "reference internal" href = "tutorial-cordapp.html" > The example CorDapp< / a > < / li >
2016-11-23 12:50:02 +00:00
< / ul >
< p class = "caption" > < span class = "caption-text" > The Corda node< / span > < / p >
< ul >
< li class = "toctree-l1" > < a class = "reference internal" href = "clientrpc.html" > Client RPC< / a > < / li >
2016-11-11 11:52:29 +00:00
< 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 >
2016-11-29 11:38:52 +00:00
< 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 >
2016-11-23 12:50:02 +00:00
< / ul >
2016-11-11 11:52:29 +00:00
< p class = "caption" > < span class = "caption-text" > Tutorials< / span > < / p >
< ul class = "current" >
< li class = "toctree-l1" > < a class = "reference internal" href = "tutorial-contract.html" > Writing a contract< / a > < / li >
< li class = "toctree-l1" > < a class = "reference internal" href = "tutorial-contract-clauses.html" > Writing a contract using clauses< / a > < / li >
< li class = "toctree-l1" > < a class = "reference internal" href = "tutorial-test-dsl.html" > Writing a contract test< / a > < / li >
2017-01-06 17:38:23 +00:00
< li class = "toctree-l1" > < a class = "reference internal" href = "tutorial-integration-testing.html" > Integration testing< / a > < / li >
2016-11-29 11:38:52 +00:00
< li class = "toctree-l1 current" > < a class = "current reference internal" href = "#" > Client RPC API tutorial< / a > < ul >
< li class = "toctree-l2" > < a class = "reference internal" href = "#registering-classes-from-your-cordapp-with-rpc-kryo" > Registering classes from your CorDapp with RPC Kryo< / a > < / li >
2016-11-29 18:44:59 +00:00
< li class = "toctree-l2" > < a class = "reference internal" href = "#security" > Security< / a > < / li >
2016-11-23 12:50:02 +00:00
< / ul >
< / li >
2017-01-06 17:38:23 +00:00
< li class = "toctree-l1" > < a class = "reference internal" href = "tutorial-building-transactions.html" > Building transactions< / a > < / li >
2016-11-25 12:10:21 +00:00
< li class = "toctree-l1" > < a class = "reference internal" href = "flow-state-machines.html" > Writing flows< / a > < / li >
< li class = "toctree-l1" > < a class = "reference internal" href = "flow-testing.html" > Writing flow tests< / a > < / li >
2016-11-29 11:38:52 +00:00
< 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 >
2016-11-11 11:52:29 +00:00
< li class = "toctree-l1" > < a class = "reference internal" href = "oracles.html" > Writing oracle services< / a > < / li >
< li class = "toctree-l1" > < a class = "reference internal" href = "tutorial-attachments.html" > Using attachments< / a > < / li >
< li class = "toctree-l1" > < a class = "reference internal" href = "event-scheduling.html" > Event scheduling< / a > < / li >
< / ul >
2016-11-23 12:50:02 +00:00
< p class = "caption" > < span class = "caption-text" > Other< / span > < / p >
2016-11-11 11:52:29 +00:00
< ul >
2016-11-23 12:50:02 +00:00
< li class = "toctree-l1" > < a class = "reference internal" href = "network-simulator.html" > Network Simulator< / a > < / li >
2017-01-26 16:57:23 +00:00
< li class = "toctree-l1" > < a class = "reference internal" href = "clauses.html" > Clauses< / a > < / li >
< li class = "toctree-l1" > < a class = "reference internal" href = "merkle-trees.html" > Transaction tear-offs< / a > < / li >
2016-11-11 11:52:29 +00:00
< / ul >
2016-11-23 12:50:02 +00:00
< p class = "caption" > < span class = "caption-text" > Component library< / span > < / p >
2016-11-11 11:52:29 +00:00
< ul >
2016-11-23 12:50:02 +00:00
< li class = "toctree-l1" > < a class = "reference internal" href = "contract-catalogue.html" > Contract catalogue< / a > < / li >
2016-11-29 11:38:52 +00:00
< li class = "toctree-l1" > < a class = "reference internal" href = "contract-irs.html" > Interest rate swaps< / a > < / li >
2016-11-11 11:52:29 +00:00
< / ul >
< p class = "caption" > < span class = "caption-text" > Appendix< / span > < / p >
< ul >
2016-11-18 12:57:39 +00:00
< li class = "toctree-l1" > < a class = "reference internal" href = "loadtesting.html" > Load testing< / a > < / li >
2017-01-06 17:38:23 +00:00
< li class = "toctree-l1" > < a class = "reference internal" href = "setting-up-a-corda-network.html" > What is a corda network?< / a > < / li >
2016-11-11 11:52:29 +00:00
< li class = "toctree-l1" > < a class = "reference internal" href = "secure-coding-guidelines.html" > Secure coding guidelines< / a > < / li >
< li class = "toctree-l1" > < a class = "reference internal" href = "release-process.html" > Release process< / a > < / li >
< li class = "toctree-l1" > < a class = "reference internal" href = "release-notes.html" > Release notes< / a > < / li >
< li class = "toctree-l1" > < a class = "reference internal" href = "codestyle.html" > Code style guide< / a > < / li >
< li class = "toctree-l1" > < a class = "reference internal" href = "building-the-docs.html" > Building the documentation< / a > < / li >
2017-01-26 16:57:23 +00:00
< li class = "toctree-l1" > < a class = "reference internal" href = "further-notes-on-kotlin.html" > Further notes on Kotlin< / a > < / li >
2017-01-03 13:07:48 +00:00
< li class = "toctree-l1" > < a class = "reference internal" href = "publishing-corda.html" > Publishing Corda< / a > < / li >
< li class = "toctree-l1" > < a class = "reference internal" href = "azure-vm.html" > Working with the Corda Demo on Azure Marketplace< / a > < / li >
2016-11-11 11:52:29 +00:00
< / ul >
2016-11-23 12:50:02 +00:00
< 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 >
2016-11-11 11:52:29 +00:00
< / 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 >
2016-11-29 11:38:52 +00:00
< li > Client RPC API tutorial< / li >
2016-11-11 11:52:29 +00:00
< li class = "wy-breadcrumbs-aside" >
< a href = "_sources/tutorial-clientrpc-api.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" >
2016-11-18 12:57:39 +00:00
< div class = "section" id = "client-rpc-api-tutorial" >
2016-11-29 11:38:52 +00:00
< h1 > Client RPC API tutorial< a class = "headerlink" href = "#client-rpc-api-tutorial" title = "Permalink to this headline" > ¶< / a > < / h1 >
2016-11-18 12:57:39 +00:00
< p > In this tutorial we will build a simple command line utility that
connects to a node, creates some Cash transactions and meanwhile dumps
the transaction graph to the standard output. We will then put some
simple visualisation on top. For an explanation on how the RPC works
see < a class = "reference internal" href = "clientrpc.html" > < span class = "doc" > Client RPC< / span > < / a > .< / p >
< p > We start off by connecting to the node itself. For the purposes of the tutorial we will use the Driver to start up a notary and a node that issues/exits and moves Cash around for herself. To authenticate we will use the certificates of the nodes directly.< / p >
2016-11-23 12:50:02 +00:00
< p > Note how we configure the node to create a user that has permission to start the CashFlow.< / p >
2017-01-06 17:38:23 +00:00
< div class = "highlight-kotlin" > < div class = "highlight" > < pre > < span > < / span > < span class = "k" > enum< / span > < span class = "k" > class< / span > < span class = "nc" > PrintOrVisualise< / span > < span class = "p" > {< / span >
< span class = "n" > Print< / span > < span class = "p" > ,< / span >
< span class = "n" > Visualise< / span >
< span class = "p" > }< / span >
< span class = "k" > fun< / span > < span class = "nf" > main< / span > < span class = "p" > (< / span > < span class = "n" > args< / span > < span class = "p" > :< / span > < span class = "n" > Array< / span > < span class = "p" > < < / span > < span class = "n" > String< / span > < span class = "p" > > )< / span > < span class = "p" > {< / span >
< span class = "n" > require< / span > < span class = "p" > (< / span > < span class = "n" > args< / span > < span class = "p" > .< / span > < span class = "n" > isNotEmpty< / span > < span class = "p" > ())< / span > < span class = "p" > {< / span > < span class = "s" > " Usage: < binary> [Print|Visualise]" < / span > < span class = "p" > }< / span >
< span class = "k" > val< / span > < span class = "py" > printOrVisualise< / span > < span class = "p" > =< / span > < span class = "n" > PrintOrVisualise< / span > < span class = "p" > .< / span > < span class = "n" > valueOf< / span > < span class = "p" > (< / span > < span class = "n" > args< / span > < span class = "p" > [< / span > < span class = "m" > 0< / span > < span class = "p" > ])< / span >
< span class = "k" > val< / span > < span class = "py" > baseDirectory< / span > < span class = "p" > =< / span > < span class = "n" > Paths< / span > < span class = "p" > .< / span > < span class = "k" > get< / span > < span class = "p" > (< / span > < span class = "s" > " build/rpc-api-tutorial" < / span > < span class = "p" > )< / span >
< span class = "k" > val< / span > < span class = "py" > user< / span > < span class = "p" > =< / span > < span class = "n" > User< / span > < span class = "p" > (< / span > < span class = "s" > " user" < / span > < span class = "p" > ,< / span > < span class = "s" > " password" < / span > < span class = "p" > ,< / span > < span class = "n" > permissions< / span > < span class = "p" > =< / span > < span class = "n" > setOf< / span > < span class = "p" > (< / span > < span class = "n" > startFlowPermission< / span > < span class = "p" > < < / span > < span class = "n" > CashFlow< / span > < span class = "p" > > ()))< / span >
2016-11-18 12:57:39 +00:00
2017-01-06 17:38:23 +00:00
< span class = "n" > driver< / span > < span class = "p" > (< / span > < span class = "n" > driverDirectory< / span > < span class = "p" > =< / span > < span class = "n" > baseDirectory< / span > < span class = "p" > )< / span > < span class = "p" > {< / span >
< span class = "n" > startNode< / span > < span class = "p" > (< / span > < span class = "s" > " Notary" < / span > < span class = "p" > ,< / span > < span class = "n" > advertisedServices< / span > < span class = "p" > =< / span > < span class = "n" > setOf< / span > < span class = "p" > (< / span > < span class = "n" > ServiceInfo< / span > < span class = "p" > (< / span > < span class = "n" > ValidatingNotaryService< / span > < span class = "p" > .< / span > < span class = "n" > type< / span > < span class = "p" > )))< / span >
< span class = "k" > val< / span > < span class = "py" > node< / span > < span class = "p" > =< / span > < span class = "n" > startNode< / span > < span class = "p" > (< / span > < span class = "s" > " Alice" < / span > < span class = "p" > ,< / span > < span class = "n" > rpcUsers< / span > < span class = "p" > =< / span > < span class = "n" > listOf< / span > < span class = "p" > (< / span > < span class = "n" > user< / span > < span class = "p" > )).< / span > < span class = "k" > get< / span > < span class = "p" > ()< / span >
2016-11-18 12:57:39 +00:00
< / pre > < / div >
< / div >
< p > Now we can connect to the node itself using a valid RPC login. We login using the configured user.< / p >
2017-01-06 17:38:23 +00:00
< div class = "highlight-kotlin" > < div class = "highlight" > < pre > < span > < / span > < span class = "k" > val< / span > < span class = "py" > client< / span > < span class = "p" > =< / span > < span class = "n" > node< / span > < span class = "p" > .< / span > < span class = "n" > rpcClientToNode< / span > < span class = "p" > ()< / span >
2016-11-18 12:57:39 +00:00
< span class = "n" > client< / span > < span class = "p" > .< / span > < span class = "n" > start< / span > < span class = "p" > (< / span > < span class = "s" > " user" < / span > < span class = "p" > ,< / span > < span class = "s" > " password" < / span > < span class = "p" > )< / span >
< span class = "k" > val< / span > < span class = "py" > proxy< / span > < span class = "p" > =< / span > < span class = "n" > client< / span > < span class = "p" > .< / span > < span class = "n" > proxy< / span > < span class = "p" > ()< / span >
< span class = "n" > thread< / span > < span class = "p" > {< / span >
< span class = "n" > generateTransactions< / span > < span class = "p" > (< / span > < span class = "n" > proxy< / span > < span class = "p" > )< / span >
< span class = "p" > }< / span >
< / pre > < / div >
< / div >
< p > We start generating transactions in a different thread (< code class = "docutils literal" > < span class = "pre" > generateTransactions< / span > < / code > to be defined later) using < code class = "docutils literal" > < span class = "pre" > proxy< / span > < / code > , which exposes the full RPC interface of the node:< / p >
2016-11-29 18:44:59 +00:00
< div class = "admonition warning" >
< p class = "first admonition-title" > Warning< / p >
< p class = "last" > This API is evolving and will continue to grow as new functionality and features added to Corda are made available to RPC clients.< / p >
< / div >
2016-11-11 11:52:29 +00:00
< p > The one we need in order to dump the transaction graph is < code class = "docutils literal" > < span class = "pre" > verifiedTransactions< / span > < / code > . The type signature tells us that the
RPC will return a list of transactions and an Observable stream. This is a general pattern, we query some data and the
2016-11-29 18:44:59 +00:00
node will return the current snapshot and future updates done to it. Observables are described in further detail in
< a class = "reference internal" href = "clientrpc.html" > < span class = "doc" > Client RPC< / span > < / a > < / p >
2016-11-18 12:57:39 +00:00
< div class = "highlight-kotlin" > < div class = "highlight" > < pre > < span > < / span > val (transactions: List< SignedTransaction> , futureTransactions: Observable< SignedTransaction> ) = proxy.verifiedTransactions()
< / pre > < / div >
< / div >
2016-11-11 11:52:29 +00:00
< p > The graph will be defined by nodes and edges between them. Each node represents a transaction and edges represent
output-input relations. For now let’ s just print < code class = "docutils literal" > < span class = "pre" > NODE< / span > < span class = "pre" > < txhash> < / span > < / code > for the former and < code class = "docutils literal" > < span class = "pre" > EDGE< / span > < span class = "pre" > < txhash> < / span > < span class = "pre" > < txhash> < / span > < / code > for the
latter.< / p >
2016-11-18 12:57:39 +00:00
< div class = "highlight-kotlin" > < div class = "highlight" > < pre > < span > < / span > < span class = "k" > when< / span > < span class = "p" > (< / span > < span class = "n" > printOrVisualise< / span > < span class = "p" > )< / span > < span class = "p" > {< / span >
< span class = "n" > PrintOrVisualise< / span > < span class = "p" > .< / span > < span class = "n" > Print< / span > < span class = "p" > -> < / span > < span class = "p" > {< / span >
< span class = "n" > futureTransactions< / span > < span class = "p" > .< / span > < span class = "n" > startWith< / span > < span class = "p" > (< / span > < span class = "n" > transactions< / span > < span class = "p" > ).< / span > < span class = "n" > subscribe< / span > < span class = "p" > {< / span > < span class = "n" > transaction< / span > < span class = "p" > -> < / span >
< span class = "n" > println< / span > < span class = "p" > (< / span > < span class = "s" > " NODE ${transaction.id}" < / span > < span class = "p" > )< / span >
< span class = "n" > transaction< / 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" > forEach< / span > < span class = "p" > {< / span > < span class = "n" > input< / span > < span class = "p" > -> < / span >
< span class = "n" > println< / span > < span class = "p" > (< / span > < span class = "s" > " EDGE ${input.txhash} ${transaction.id}" < / span > < span class = "p" > )< / span >
< span class = "p" > }< / span >
< span class = "p" > }< / span >
< span class = "p" > }< / span >
2016-11-11 11:52:29 +00:00
< / pre > < / div >
< / div >
2016-11-18 12:57:39 +00:00
< p > Now we just need to create the transactions themselves!< / p >
< div class = "highlight-kotlin" > < div class = "highlight" > < pre > < span > < / span > < span class = "k" > fun< / span > < span class = "nf" > generateTransactions< / span > < span class = "p" > (< / span > < span class = "n" > proxy< / span > < span class = "p" > :< / span > < span class = "n" > CordaRPCOps< / span > < span class = "p" > )< / span > < span class = "p" > {< / span >
< span class = "k" > var< / span > < span class = "py" > ownedQuantity< / span > < span class = "p" > =< / span > < span class = "n" > proxy< / span > < span class = "p" > .< / span > < span class = "n" > vaultAndUpdates< / span > < span class = "p" > ().< / span > < span class = "n" > first< / span > < span class = "p" > .< / span > < span class = "n" > fold< / span > < span class = "p" > (< / span > < span class = "m" > 0L< / span > < span class = "p" > )< / span > < span class = "p" > {< / span > < span class = "n" > sum< / span > < span class = "p" > ,< / span > < span class = "n" > state< / span > < span class = "p" > -> < / span >
< span class = "n" > sum< / span > < span class = "p" > +< / 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 = "k" > as< / span > < span class = "n" > Cash< / 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" > quantity< / span >
< span class = "p" > }< / span >
< span class = "k" > val< / span > < span class = "py" > issueRef< / span > < span class = "p" > =< / span > < span class = "n" > OpaqueBytes< / span > < span class = "p" > .< / span > < span class = "n" > of< / span > < span class = "p" > (< / span > < span class = "m" > 0< / span > < span class = "p" > )< / span >
< span class = "k" > val< / span > < span class = "py" > notary< / span > < span class = "p" > =< / span > < span class = "n" > proxy< / span > < span class = "p" > .< / span > < span class = "n" > networkMapUpdates< / span > < span class = "p" > ().< / span > < span class = "n" > first< / span > < span class = "p" > .< / span > < span class = "n" > first< / span > < span class = "p" > {< / span > < span class = "n" > it< / span > < span class = "p" > .< / span > < span class = "n" > advertisedServices< / span > < span class = "p" > .< / span > < span class = "n" > any< / span > < span class = "p" > {< / span > < span class = "n" > it< / span > < span class = "p" > .< / span > < span class = "n" > info< / span > < span class = "p" > .< / span > < span class = "n" > type< / span > < span class = "p" > .< / span > < span class = "n" > isNotary< / span > < span class = "p" > ()< / span > < span class = "p" > }< / span > < span class = "p" > }.< / span > < span class = "n" > notaryIdentity< / span >
< span class = "k" > val< / span > < span class = "py" > me< / span > < span class = "p" > =< / span > < span class = "n" > proxy< / span > < span class = "p" > .< / span > < span class = "n" > nodeIdentity< / span > < span class = "p" > ().< / span > < span class = "n" > legalIdentity< / span >
< span class = "k" > val< / span > < span class = "py" > meAndRef< / span > < span class = "p" > =< / span > < span class = "n" > PartyAndReference< / span > < span class = "p" > (< / span > < span class = "n" > me< / span > < span class = "p" > ,< / span > < span class = "n" > issueRef< / span > < span class = "p" > )< / span >
< span class = "k" > while< / span > < span class = "p" > (< / span > < span class = "k" > true< / span > < span class = "p" > )< / span > < span class = "p" > {< / span >
< span class = "n" > Thread< / span > < span class = "p" > .< / span > < span class = "n" > sleep< / span > < span class = "p" > (< / span > < span class = "m" > 1000< / span > < span class = "p" > )< / span >
< span class = "k" > val< / span > < span class = "py" > random< / span > < span class = "p" > =< / span > < span class = "n" > SplittableRandom< / span > < span class = "p" > ()< / span >
< span class = "k" > val< / span > < span class = "py" > n< / span > < span class = "p" > =< / span > < span class = "n" > random< / span > < span class = "p" > .< / span > < span class = "n" > nextDouble< / span > < span class = "p" > ()< / span >
< span class = "k" > if< / span > < span class = "p" > (< / span > < span class = "n" > ownedQuantity< / span > < span class = "p" > > < / span > < span class = "m" > 10000< / span > < span class = "p" > & & < / span > < span class = "n" > n< / span > < span class = "p" > > < / span > < span class = "m" > 0.8< / span > < span class = "p" > )< / span > < span class = "p" > {< / span >
< span class = "k" > val< / span > < span class = "py" > quantity< / span > < span class = "p" > =< / span > < span class = "n" > Math< / span > < span class = "p" > .< / span > < span class = "n" > abs< / span > < span class = "p" > (< / span > < span class = "n" > random< / span > < span class = "p" > .< / span > < span class = "n" > nextLong< / span > < span class = "p" > ())< / span > < span class = "p" > %< / span > < span class = "m" > 2000< / span >
2016-11-23 12:50:02 +00:00
< span class = "n" > proxy< / span > < span class = "p" > .< / span > < span class = "n" > startFlow< / span > < span class = "p" > (< / span > < span class = "o" > ::< / span > < span class = "n" > CashFlow< / span > < span class = "p" > ,< / span > < span class = "n" > CashCommand< / span > < span class = "p" > .< / span > < span class = "n" > ExitCash< / 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" > USD< / span > < span class = "p" > ),< / span > < span class = "n" > issueRef< / span > < span class = "p" > ))< / span >
2016-11-18 12:57:39 +00:00
< span class = "n" > ownedQuantity< / span > < span class = "p" > -=< / span > < span class = "n" > quantity< / span >
< span class = "p" > }< / span > < span class = "k" > else< / span > < span class = "k" > if< / span > < span class = "p" > (< / span > < span class = "n" > ownedQuantity< / span > < span class = "p" > > < / span > < span class = "m" > 1000< / span > < span class = "p" > & & < / span > < span class = "n" > n< / span > < span class = "p" > < < / span > < span class = "m" > 0.7< / span > < span class = "p" > )< / span > < span class = "p" > {< / span >
< span class = "k" > val< / span > < span class = "py" > quantity< / span > < span class = "p" > =< / span > < span class = "n" > Math< / span > < span class = "p" > .< / span > < span class = "n" > abs< / span > < span class = "p" > (< / span > < span class = "n" > random< / span > < span class = "p" > .< / span > < span class = "n" > nextLong< / span > < span class = "p" > ()< / span > < span class = "p" > %< / span > < span class = "n" > Math< / span > < span class = "p" > .< / span > < span class = "n" > min< / span > < span class = "p" > (< / span > < span class = "n" > ownedQuantity< / span > < span class = "p" > ,< / span > < span class = "m" > 2000< / span > < span class = "p" > ))< / span >
2016-11-23 12:50:02 +00:00
< span class = "n" > proxy< / span > < span class = "p" > .< / span > < span class = "n" > startFlow< / span > < span class = "p" > (< / span > < span class = "o" > ::< / span > < span class = "n" > CashFlow< / span > < span class = "p" > ,< / span > < span class = "n" > CashCommand< / span > < span class = "p" > .< / span > < span class = "n" > PayCash< / 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" > Issued< / span > < span class = "p" > (< / span > < span class = "n" > meAndRef< / span > < span class = "p" > ,< / span > < span class = "n" > USD< / span > < span class = "p" > )),< / span > < span class = "n" > me< / span > < span class = "p" > ))< / span >
2016-11-18 12:57:39 +00:00
< span class = "p" > }< / span > < span class = "k" > else< / span > < span class = "p" > {< / span >
< span class = "k" > val< / span > < span class = "py" > quantity< / span > < span class = "p" > =< / span > < span class = "n" > Math< / span > < span class = "p" > .< / span > < span class = "n" > abs< / span > < span class = "p" > (< / span > < span class = "n" > random< / span > < span class = "p" > .< / span > < span class = "n" > nextLong< / span > < span class = "p" > ()< / span > < span class = "p" > %< / span > < span class = "m" > 1000< / span > < span class = "p" > )< / span >
2016-11-23 12:50:02 +00:00
< span class = "n" > proxy< / span > < span class = "p" > .< / span > < span class = "n" > startFlow< / span > < span class = "p" > (< / span > < span class = "o" > ::< / span > < span class = "n" > CashFlow< / span > < span class = "p" > ,< / span > < span class = "n" > CashCommand< / span > < span class = "p" > .< / span > < span class = "n" > IssueCash< / 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" > USD< / span > < span class = "p" > ),< / span > < span class = "n" > issueRef< / span > < span class = "p" > ,< / span > < span class = "n" > me< / span > < span class = "p" > ,< / span > < span class = "n" > notary< / span > < span class = "p" > ))< / span >
2016-11-18 12:57:39 +00:00
< span class = "n" > ownedQuantity< / span > < span class = "p" > +=< / span > < span class = "n" > quantity< / span >
< span class = "p" > }< / span >
< span class = "p" > }< / span >
< span class = "p" > }< / span >
2016-11-11 11:52:29 +00:00
< / pre > < / div >
< / div >
2016-11-18 12:57:39 +00:00
< p > We utilise several RPC functions here to query things like the notaries in the node cluster or our own vault.< / p >
< p > Then in a loop we generate randomly either an Issue, a Pay or an Exit transaction.< / p >
2016-11-23 12:50:02 +00:00
< p > The RPC we need to initiate a Cash transaction is < code class = "docutils literal" > < span class = "pre" > startFlowDynamic< / span > < / code > which may start an arbitrary flow, given sufficient permissions to do so. We won’ t use this function directly, but rather a type-safe wrapper around it < code class = "docutils literal" > < span class = "pre" > startFlow< / span > < / code > that type-checks the arguments for us.< / p >
2016-11-18 12:57:39 +00:00
< p > Finally we have everything in place: we start a couple of nodes, connect to them, and start creating transactions while listening on successfully created ones, which are dumped to the console. We just need to run it!:< / p >
2016-11-29 18:44:59 +00:00
< div class = "highlight-text" > < div class = "highlight" > < pre > < span > < / span > # Build the example
2016-11-18 12:57:39 +00:00
./gradlew docs/source/example-code:installDist
2016-11-29 18:44:59 +00:00
# Start it
2016-11-29 11:38:52 +00:00
./docs/source/example-code/build/install/docs/source/example-code/bin/client-rpc-tutorial Print
< / pre > < / div >
< / div >
2016-11-18 12:57:39 +00:00
< p > Now let’ s try to visualise the transaction graph. We will use a graph drawing library called < a class = "reference external" href = "http://graphstream-project.org/" > graphstream< / a > < / p >
< div class = "highlight-kotlin" > < div class = "highlight" > < pre > < span > < / span > < span class = "n" > PrintOrVisualise< / span > < span class = "p" > .< / span > < span class = "n" > Visualise< / span > < span class = "p" > -> < / span > < span class = "p" > {< / span >
< span class = "k" > val< / span > < span class = "py" > graph< / span > < span class = "p" > =< / span > < span class = "n" > MultiGraph< / span > < span class = "p" > (< / span > < span class = "s" > " transactions" < / span > < span class = "p" > )< / span >
< span class = "n" > transactions< / span > < span class = "p" > .< / span > < span class = "n" > forEach< / span > < span class = "p" > {< / span > < span class = "n" > transaction< / span > < span class = "p" > -> < / span >
< span class = "n" > graph< / span > < span class = "p" > .< / span > < span class = "n" > addNode< / span > < span class = "p" > < < / span > < span class = "n" > Node< / span > < span class = "p" > > (< / span > < span class = "s" > " ${transaction.id}" < / span > < span class = "p" > )< / span >
< span class = "p" > }< / span >
< span class = "n" > transactions< / span > < span class = "p" > .< / span > < span class = "n" > forEach< / span > < span class = "p" > {< / span > < span class = "n" > transaction< / span > < span class = "p" > -> < / span >
< span class = "n" > transaction< / 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" > forEach< / span > < span class = "p" > {< / span > < span class = "n" > ref< / span > < span class = "p" > -> < / span >
< span class = "n" > graph< / span > < span class = "p" > .< / span > < span class = "n" > addEdge< / span > < span class = "p" > < < / span > < span class = "n" > Edge< / span > < span class = "p" > > (< / span > < span class = "s" > " $ref" < / span > < span class = "p" > ,< / span > < span class = "s" > " ${ref.txhash}" < / span > < span class = "p" > ,< / span > < span class = "s" > " ${transaction.id}" < / span > < span class = "p" > )< / span >
< span class = "p" > }< / span >
< span class = "p" > }< / span >
< span class = "n" > futureTransactions< / span > < span class = "p" > .< / span > < span class = "n" > subscribe< / span > < span class = "p" > {< / span > < span class = "n" > transaction< / span > < span class = "p" > -> < / span >
< span class = "n" > graph< / span > < span class = "p" > .< / span > < span class = "n" > addNode< / span > < span class = "p" > < < / span > < span class = "n" > Node< / span > < span class = "p" > > (< / span > < span class = "s" > " ${transaction.id}" < / span > < span class = "p" > )< / span >
< span class = "n" > transaction< / 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" > forEach< / span > < span class = "p" > {< / span > < span class = "n" > ref< / span > < span class = "p" > -> < / span >
< span class = "n" > graph< / span > < span class = "p" > .< / span > < span class = "n" > addEdge< / span > < span class = "p" > < < / span > < span class = "n" > Edge< / span > < span class = "p" > > (< / span > < span class = "s" > " $ref" < / span > < span class = "p" > ,< / span > < span class = "s" > " ${ref.txhash}" < / span > < span class = "p" > ,< / span > < span class = "s" > " ${transaction.id}" < / span > < span class = "p" > )< / span >
< span class = "p" > }< / span >
< span class = "p" > }< / span >
< span class = "n" > graph< / span > < span class = "p" > .< / span > < span class = "n" > display< / span > < span class = "p" > ()< / span >
< span class = "p" > }< / span >
< span class = "p" > }< / span >
< span class = "n" > waitForAllNodesToFinish< / span > < span class = "p" > ()< / span >
< span class = "p" > }< / span >
< span class = "p" > }< / span >
2016-11-11 11:52:29 +00:00
< / pre > < / div >
< / div >
2016-11-18 12:57:39 +00:00
< p > If we run the client with < code class = "docutils literal" > < span class = "pre" > Visualise< / span > < / code > we should see a simple random graph being drawn as new transactions are being created.< / p >
2016-11-23 12:50:02 +00:00
< div class = "section" id = "registering-classes-from-your-cordapp-with-rpc-kryo" >
2016-11-29 11:38:52 +00:00
< h2 > Registering classes from your CorDapp with RPC Kryo< a class = "headerlink" href = "#registering-classes-from-your-cordapp-with-rpc-kryo" title = "Permalink to this headline" > ¶< / a > < / h2 >
2016-11-23 12:50:02 +00:00
< p > As described in < a class = "reference internal" href = "clientrpc.html" > < span class = "doc" > Client RPC< / span > < / a > , you currently have to register any additional classes you add that are needed in RPC
requests or responses with the < cite > Kryo< / cite > instance RPC uses. Here’ s an example of how you do this for an example class.< / p >
< div class = "highlight-kotlin" > < div class = "highlight" > < pre > < span > < / span > < span class = "k" > data< / span > < span class = "k" > class< / span > < span class = "nc" > ExampleRPCValue< / span > < span class = "p" > (< / span > < span class = "k" > val< / span > < span class = "py" > foo< / span > < span class = "p" > :< / span > < span class = "n" > String< / span > < span class = "p" > )< / span >
< span class = "k" > class< / span > < span class = "nc" > ExampleRPCCordaPluginRegistry< / span > < span class = "p" > :< / span > < span class = "n" > CordaPluginRegistry< / span > < span class = "p" > ()< / span > < span class = "p" > {< / span >
< span class = "k" > override< / span > < span class = "k" > fun< / span > < span class = "nf" > registerRPCKryoTypes< / span > < span class = "p" > (< / span > < span class = "n" > kryo< / span > < span class = "p" > :< / span > < span class = "n" > Kryo< / span > < span class = "p" > ):< / span > < span class = "n" > Boolean< / span > < span class = "p" > {< / span >
< span class = "c1" > // Add classes like this.< / span >
< span class = "n" > kryo< / span > < span class = "p" > .< / span > < span class = "n" > register< / span > < span class = "p" > (< / span > < span class = "n" > ExampleRPCValue< / span > < span class = "o" > ::< / span > < span class = "k" > class< / span > < span class = "p" > .< / span > < span class = "n" > java< / span > < span class = "p" > )< / span >
< span class = "c1" > // You should return true, otherwise your plugin will be ignored for registering classes with Kryo.< / span >
< span class = "k" > return< / span > < span class = "k" > true< / span >
< span class = "p" > }< / span >
< span class = "p" > }< / span >
< / pre > < / div >
< / div >
2017-01-06 17:38:23 +00:00
< p > See more on plugins in < a class = "reference internal" href = "creating-a-cordapp.html" > < span class = "doc" > CorDapp basics< / span > < / a > .< / p >
2016-11-23 12:50:02 +00:00
< div class = "admonition warning" >
< p class = "first admonition-title" > Warning< / p >
< p class = "last" > We will be replacing the use of Kryo in RPC with a stable message format and this will mean that this plugin
customisation point will either go away completely or change.< / p >
< / div >
< / div >
2016-11-29 18:44:59 +00:00
< div class = "section" id = "security" >
< h2 > Security< a class = "headerlink" href = "#security" title = "Permalink to this headline" > ¶< / a > < / h2 >
< p > RPC credentials associated with a Client must match the permission set configured on the server Node.
This refers to both authentication (username and password) and role-based authorisation (a permissioned set of RPC operations an
authenticated user is entitled to run).< / p >
< div class = "admonition note" >
< p class = "first admonition-title" > Note< / p >
< p class = "last" > Permissions are represented as < em > String’ s< / em > to allow RPC implementations to add their own permissioning.
Currently the only permission type defined is < em > StartFlow< / em > , which defines a list of whitelisted flows an authenticated use may execute.< / p >
< / div >
< p > In the instructions above the server node permissions are configured programmatically in the driver code:< / p >
< div class = "highlight-text" > < div class = "highlight" > < pre > < span > < / span > driver(driverDirectory = baseDirectory) {
val user = User(" user" , " password" , permissions = setOf(startFlowPermission< CashFlow> ()))
val node = startNode(" Alice" , rpcUsers = listOf(user)).get()
< / pre > < / div >
< / div >
< p > When starting a standalone node using a configuration file we must supply the RPC credentials as follows:< / p >
< div class = "highlight-text" > < div class = "highlight" > < pre > < span > < / span > rpcUsers : [
{ user=user, password=password, permissions=[ StartFlow.net.corda.flows.CashFlow ] }
]
< / pre > < / div >
< / div >
< p > When using the gradle Cordformation plugin to configure and deploy a node you must supply the RPC credentials in a similar manner:< / p >
< div class = "highlight-text" > < div class = "highlight" > < pre > < span > < / span > rpcUsers = [
[' user' : " user" ,
' password' : " password" ,
' permissions' : [" StartFlow.net.corda.flows.CashFlow" ]]
]
< / pre > < / div >
< / div >
< p > You can then deploy and launch the nodes (Notary and Alice) as follows:< / p >
< div class = "highlight-text" > < div class = "highlight" > < pre > < span > < / span > # to create a set of configs and installs under ``docs/source/example-code/build/nodes`` run
./gradlew docs/source/example-code:deployNodes
# to open up two new terminals with the two nodes run
./docs/source/example-code/build/nodes/runnodes
# followed by the same commands as before:
./docs/source/example-code/build/install/docs/source/example-code/bin/client-rpc-tutorial Print
./docs/source/example-code/build/install/docs/source/example-code/bin/client-rpc-tutorial Visualise
< / pre > < / div >
< / div >
< p > See more on security in < a class = "reference internal" href = "secure-coding-guidelines.html" > < span class = "doc" > Secure coding guidelines< / span > < / a > , node configuration in < a class = "reference internal" href = "corda-configuration-file.html" > < span class = "doc" > Node configuration< / span > < / a > and
2017-01-06 17:38:23 +00:00
Cordformation in < a class = "reference internal" href = "creating-a-cordapp.html" > < span class = "doc" > CorDapp basics< / span > < / a > < / p >
2016-11-29 18:44:59 +00:00
< / div >
2016-11-11 11:52:29 +00:00
< / div >
< / div >
< / div >
< footer >
< div class = "rst-footer-buttons" role = "navigation" aria-label = "footer navigation" >
2017-01-06 17:38:23 +00:00
< a href = "tutorial-building-transactions.html" class = "btn btn-neutral float-right" title = "Building transactions" accesskey = "n" > Next < span class = "fa fa-arrow-circle-right" > < / span > < / a >
2016-11-11 11:52:29 +00:00
2017-01-06 17:38:23 +00:00
< a href = "tutorial-integration-testing.html" class = "btn btn-neutral" title = "Integration testing" accesskey = "p" > < span class = "fa fa-arrow-circle-left" > < / span > Previous< / a >
2016-11-11 11:52:29 +00:00
< / div >
< hr / >
< div role = "contentinfo" >
< p >
2016-11-29 18:44:59 +00:00
© Copyright 2016, R3 Limited.
2016-11-11 11:52:29 +00:00
< / p >
< / div >
Built with < a href = "http://sphinx-doc.org/" > Sphinx< / a > using a < a href = "https://github.com/snide/sphinx_rtd_theme" > theme< / a > provided by < a href = "https://readthedocs.org" > Read the Docs< / a > .
< / footer >
< / div >
< / div >
< / section >
< / div >
< script type = "text/javascript" >
var DOCUMENTATION_OPTIONS = {
URL_ROOT:'./',
VERSION:'latest',
COLLAPSE_INDEX:false,
FILE_SUFFIX:'.html',
HAS_SOURCE: true
};
< / script >
< script type = "text/javascript" src = "_static/jquery.js" > < / script >
< script type = "text/javascript" src = "_static/underscore.js" > < / script >
< script type = "text/javascript" src = "_static/doctools.js" > < / script >
< script type = "text/javascript" src = "_static/js/theme.js" > < / script >
< script type = "text/javascript" >
jQuery(function () {
SphinxRtdTheme.StickyNav.enable();
});
< / script >
< / body >
< / html >