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" >
< title > Writing oracle services — 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 = "Using attachments" href = "tutorial-attachments.html" / >
2016-11-29 18:44:59 +00:00
< link rel = "prev" title = "Using a notary service" href = "using-a-notary.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 >
< li class = "toctree-l1" > < a class = "reference internal" href = "tutorial-cordapp.html" > The CorDapp template< / 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 18:44:59 +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-11 11:52:29 +00:00
< / ul >
< p class = "caption" > < span class = "caption-text" > Tutorials< / span > < / p >
< ul class = "current" >
< li class = "toctree-l1" > < a class = "reference internal" href = "tutorial-contract.html" > Writing a contract< / a > < / li >
< li class = "toctree-l1" > < a class = "reference internal" href = "tutorial-contract-clauses.html" > Writing a contract using clauses< / a > < / li >
< li class = "toctree-l1" > < a class = "reference internal" href = "tutorial-test-dsl.html" > Writing a contract test< / a > < / li >
2017-01-06 17:38:23 +00:00
< li class = "toctree-l1" > < a class = "reference internal" href = "tutorial-integration-testing.html" > Integration testing< / a > < / li >
2016-11-29 18:44:59 +00:00
< li class = "toctree-l1" > < a class = "reference internal" href = "tutorial-clientrpc-api.html" > Client RPC API tutorial< / a > < / li >
2017-01-06 17:38:23 +00:00
< li class = "toctree-l1" > < a class = "reference internal" href = "tutorial-building-transactions.html" > Building transactions< / a > < / li >
2016-11-29 18:44:59 +00:00
< li class = "toctree-l1" > < a class = "reference internal" href = "flow-state-machines.html" > Writing flows< / a > < / li >
< li class = "toctree-l1" > < a class = "reference internal" href = "flow-testing.html" > Writing flow tests< / a > < / li >
< li class = "toctree-l1" > < a class = "reference internal" href = "running-a-notary.html" > Running a notary service< / a > < / li >
< li class = "toctree-l1" > < 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 current" > < a class = "current reference internal" href = "#" > Writing oracle services< / a > < ul >
2017-01-06 17:38:23 +00:00
< li class = "toctree-l2" > < a class = "reference internal" href = "#introduction-to-oracles" > Introduction to oracles< / a > < ul >
< li class = "toctree-l3" > < a class = "reference internal" href = "#the-two-basic-approaches" > The two basic approaches< / a > < / li >
< li class = "toctree-l3" > < a class = "reference internal" href = "#asserting-continuously-varying-data" > Asserting continuously varying data< / a > < / li >
< li class = "toctree-l3" > < a class = "reference internal" href = "#hiding-transaction-data-from-the-oracle" > Hiding transaction data from the oracle< / a > < / li >
< li class = "toctree-l3" > < a class = "reference internal" href = "#pay-per-play-oracles" > Pay-per-play oracles< / a > < / li >
2016-11-11 11:52:29 +00:00
< / ul >
< / li >
2017-01-06 17:38:23 +00:00
< li class = "toctree-l2" > < a class = "reference internal" href = "#implementing-an-oracle-with-continuously-varying-data" > Implementing an oracle with continuously varying data< / a > < ul >
< li class = "toctree-l3" > < a class = "reference internal" href = "#implement-the-core-classes" > Implement the core classes< / a > < / li >
< li class = "toctree-l3" > < a class = "reference internal" href = "#binding-to-the-network-via-a-cordapp-plugin" > Binding to the network via a CorDapp plugin< / a > < / li >
< li class = "toctree-l3" > < a class = "reference internal" href = "#providing-client-sub-flows-for-querying-and-signing" > Providing client sub-flows for querying and signing< / a > < / li >
< / ul >
< / li >
< li class = "toctree-l2" > < a class = "reference internal" href = "#using-an-oracle" > Using an oracle< / a > < / li >
2016-11-29 18:44:59 +00:00
< / ul >
< / li >
2016-11-11 11:52:29 +00:00
< 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 18:44:59 +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 >
< li > Writing oracle services< / li >
< li class = "wy-breadcrumbs-aside" >
< a href = "_sources/oracles.txt" rel = "nofollow" > View page source< / a >
< / li >
< / ul >
< hr / >
< / div >
< div role = "main" class = "document" itemscope = "itemscope" itemtype = "http://schema.org/Article" >
< div itemprop = "articleBody" >
< script type = "text/javascript" src = "_static/jquery.js" > < / script >
< script type = "text/javascript" src = "_static/codesets.js" > < / script > < div class = "section" id = "writing-oracle-services" >
< h1 > Writing oracle services< a class = "headerlink" href = "#writing-oracle-services" title = "Permalink to this headline" > ¶< / a > < / h1 >
< p > This article covers < em > oracles< / em > : network services that link the ledger to the outside world by providing facts that
affect the validity of transactions.< / p >
< p > The current prototype includes an example oracle that provides an interest rate fixing service. It is used by the
IRS trading demo app.< / p >
2017-01-06 17:38:23 +00:00
< div class = "section" id = "introduction-to-oracles" >
< h2 > Introduction to oracles< a class = "headerlink" href = "#introduction-to-oracles" title = "Permalink to this headline" > ¶< / a > < / h2 >
2016-11-11 11:52:29 +00:00
< p > Oracles are a key concept in the block chain/decentralised ledger space. They can be essential for many kinds of
application, because we often wish to condition a transaction on some fact being true or false, but the ledger itself
has a design that is essentially functional: all transactions are < em > pure< / em > and < em > immutable< / em > . Phrased another way, a
smart contract cannot perform any input/output or depend on any state outside of the transaction itself. There is no
way to download a web page or interact with the user, in a smart contract. It must be this way because everyone must
2017-01-06 17:38:23 +00:00
be able to independently check a transaction and arrive at an identical conclusion for the ledger to maintain its
2016-11-11 11:52:29 +00:00
integrity: if a transaction could evaluate to “ valid” on one computer and then “ invalid” a few minutes later on a
different computer, the entire shared ledger concept wouldn’ t work.< / p >
< p > But it is often essential that transactions do depend on data from the outside world, for example, verifying that an
interest rate swap is paying out correctly may require data on interest rates, verifying that a loan has reached
maturity requires knowledge about the current time, knowing which side of a bet receives the payment may require
arbitrary facts about the real world (e.g. the bankruptcy or solvency of a company or country) ... and so on.< / p >
< p > We can solve this problem by introducing services that create digitally signed data structures which assert facts.
These structures can then be used as an input to a transaction and distributed with the transaction data itself. Because
the statements are themselves immutable and signed, it is impossible for an oracle to change its mind later and
invalidate transactions that were previously found to be valid. In contrast, consider what would happen if a contract
could do an HTTP request: it’ s possible that an answer would change after being downloaded, resulting in loss of
consensus (breaks).< / p >
< div class = "section" id = "the-two-basic-approaches" >
2017-01-06 17:38:23 +00:00
< h3 > The two basic approaches< a class = "headerlink" href = "#the-two-basic-approaches" title = "Permalink to this headline" > ¶< / a > < / h3 >
2016-11-11 11:52:29 +00:00
< p > The architecture provides two ways of implementing oracles with different tradeoffs:< / p >
< ol class = "arabic simple" >
< li > Using commands< / li >
< li > Using attachments< / li >
< / ol >
< p > When a fact is encoded in a command, it is embedded in the transaction itself. The oracle then acts as a co-signer to
the entire transaction. The oracle’ s signature is valid only for that transaction, and thus even if a fact (like a
stock price) does not change, every transaction that incorporates that fact must go back to the oracle for signing.< / p >
< p > When a fact is encoded as an attachment, it is a separate object to the transaction and is referred to by hash.
Nodes download attachments from peers at the same time as they download transactions, unless of course the node has
already seen that attachment, in which case it won’ t fetch it again. Contracts have access to the contents of
attachments when they run.< / p >
< div class = "admonition note" >
< p class = "first admonition-title" > Note< / p >
< p class = "last" > Currently attachments do not support digital signing, but this is a planned feature.< / p >
< / div >
< p > As you can see, both approaches share a few things: they both allow arbitrary binary data to be provided to transactions
(and thus contracts). The primary difference is whether the data is a freely reusable, standalone object or whether it’ s
integrated with a transaction.< / p >
< p > Here’ s a quick way to decide which approach makes more sense for your data source:< / p >
< ul class = "simple" >
< li > Is your data < em > continuously changing< / em > , like a stock price, the current time, etc? If yes, use a command.< / li >
< li > Is your data < em > commercially valuable< / em > , like a feed which you are not allowed to resell unless it’ s incorporated into
a business deal? If yes, use a command, so you can charge money for signing the same fact in each unique business
context.< / li >
< li > Is your data < em > very small< / em > , like a single number? If yes, use a command.< / li >
< li > Is your data < em > large< / em > , < em > static< / em > and < em > commercially worthless< / em > , for instance, a holiday calendar? If yes, use an
attachment.< / li >
< li > Is your data < em > intended for human consumption< / em > , like a PDF of legal prose, or an Excel spreadsheet? If yes, use an
attachment.< / li >
< / ul >
< / div >
< div class = "section" id = "asserting-continuously-varying-data" >
2017-01-06 17:38:23 +00:00
< h3 > Asserting continuously varying data< a class = "headerlink" href = "#asserting-continuously-varying-data" title = "Permalink to this headline" > ¶< / a > < / h3 >
2016-11-11 11:52:29 +00:00
< p > Let’ s look at the interest rates oracle that can be found in the < code class = "docutils literal" > < span class = "pre" > NodeInterestRates< / span > < / code > file. This is an example of
an oracle that uses a command because the current interest rate fix is a constantly changing fact.< / p >
< p > The obvious way to implement such a service is like this:< / p >
< ol class = "arabic simple" >
< li > The creator of the transaction that depends on the interest rate sends it to the oracle.< / li >
< li > The oracle inserts a command with the rate and signs the transaction.< / li >
< li > The oracle sends it back.< / li >
< / ol >
< p > But this has a problem - it would mean that the oracle has to be the first entity to sign the transaction, which might impose
ordering constraints we don’ t want to deal with (being able to get all parties to sign in parallel is a very nice thing).
So the way we actually implement it is like this:< / p >
< ol class = "arabic simple" >
< li > The creator of the transaction that depends on the interest rate asks for the current rate. They can abort at this point
if they want to.< / li >
< li > They insert a command with that rate and the time it was obtained into the transaction.< / li >
2016-11-29 18:44:59 +00:00
< li > They then send it to the oracle for signing, along with everyone else, potentially in parallel. The oracle checks that
the command has the correct data for the asserted time, and signs if so.< / li >
2016-11-11 11:52:29 +00:00
< / ol >
< p > This same technique can be adapted to other types of oracle.< / p >
< p > The oracle consists of a core class that implements the query/sign operations (for easy unit testing), and then a separate
class that binds it to the network layer.< / p >
2016-11-29 18:44:59 +00:00
< p > Here is an extract from the < code class = "docutils literal" > < span class = "pre" > NodeInterestRates.Oracle< / span > < / code > class and supporting types:< / p >
2016-11-11 11:52:29 +00:00
< div class = "highlight-kotlin" > < div class = "highlight" > < pre > < span > < / span > < span class = "cm" > /** A [FixOf] identifies the question side of a fix: what day, tenor and type of fix (" LIBOR" , " EURIBOR" etc) */< / span >
< span class = "k" > data< / span > < span class = "k" > class< / span > < span class = "nc" > FixOf< / span > < span class = "p" > (< / span > < span class = "k" > val< / span > < span class = "py" > name< / span > < span class = "p" > :< / span > < span class = "n" > String< / span > < span class = "p" > ,< / span > < span class = "k" > val< / span > < span class = "py" > forDay< / span > < span class = "p" > :< / span > < span class = "n" > LocalDate< / span > < span class = "p" > ,< / span > < span class = "k" > val< / span > < span class = "py" > ofTenor< / span > < span class = "p" > :< / span > < span class = "n" > Duration< / span > < span class = "p" > )< / span >
< span class = "cm" > /** A [Fix] represents a named interest rate, on a given day, for a given duration. It can be embedded in a tx. */< / span >
< span class = "k" > data< / span > < span class = "k" > class< / span > < span class = "nc" > Fix< / span > < span class = "p" > (< / span > < span class = "k" > val< / span > < span class = "py" > of< / span > < span class = "p" > :< / span > < span class = "n" > FixOf< / span > < span class = "p" > ,< / span > < span class = "k" > val< / span > < span class = "py" > value< / span > < span class = "p" > :< / span > < span class = "n" > BigDecimal< / span > < span class = "p" > )< / span > < span class = "p" > :< / span > < span class = "n" > CommandData< / span >
< span class = "k" > class< / span > < span class = "nc" > Oracle< / span > < span class = "p" > {< / span >
2016-11-29 18:44:59 +00:00
< span class = "k" > fun< / span > < span class = "nf" > query< / span > < span class = "p" > (< / span > < span class = "n" > queries< / span > < span class = "p" > :< / span > < span class = "n" > List< / span > < span class = "p" > < < / span > < span class = "n" > FixOf< / span > < span class = "p" > > ,< / span > < span class = "n" > deadline< / span > < span class = "p" > :< / span > < span class = "n" > Instant< / span > < span class = "p" > ):< / span > < span class = "n" > List< / span > < span class = "p" > < < / span > < span class = "n" > Fix< / span > < span class = "p" > > < / span >
2016-11-11 11:52:29 +00:00
2016-11-29 18:44:59 +00:00
< span class = "k" > fun< / span > < span class = "nf" > sign< / span > < span class = "p" > (< / span > < span class = "n" > ftx< / span > < span class = "p" > :< / span > < span class = "n" > FilteredTransaction< / span > < span class = "p" > ,< / span > < span class = "n" > merkleRoot< / span > < span class = "p" > :< / span > < span class = "n" > SecureHash< / span > < span class = "p" > ):< / span > < span class = "n" > DigitalSignature< / span > < span class = "p" > .< / span > < span class = "n" > LegallyIdentifiable< / span >
2016-11-11 11:52:29 +00:00
< span class = "p" > }< / span >
< / pre > < / div >
< / div >
2016-11-29 18:44:59 +00:00
< p > Because the fix contains a timestamp (the < code class = "docutils literal" > < span class = "pre" > forDay< / span > < / code > field), that identifies the version of the data being requested,
there can be an arbitrary delay between a fix being requested via < code class = "docutils literal" > < span class = "pre" > query< / span > < / code > and the signature being requested via < code class = "docutils literal" > < span class = "pre" > sign< / span > < / code >
as the Oracle can know which, potentially historical, value it is being asked to sign for. This is an important
technique for continously varying data.< / p >
< p > The < code class = "docutils literal" > < span class = "pre" > query< / span > < / code > method takes a deadline, which is a point in time the requester is willing to wait until for the necessary
data to be available. Not every oracle will need this. This can be useful where data is expected to be available on a
particular schedule and we use scheduling functionality to automatically launch the processing associated with it.
We can schedule for the expected announcement (or publish) time and give a suitable deadline at which the lack of the
information being available and the delay to processing becomes significant and may need to be escalated.< / p >
< / div >
< div class = "section" id = "hiding-transaction-data-from-the-oracle" >
2017-01-06 17:38:23 +00:00
< h3 > Hiding transaction data from the oracle< a class = "headerlink" href = "#hiding-transaction-data-from-the-oracle" title = "Permalink to this headline" > ¶< / a > < / h3 >
2016-11-29 18:44:59 +00:00
< p > Because the transaction is sent to the oracle for signing, ordinarily the oracle would be able to see the entire contents
of that transaction including the inputs, output contract states and all the commands, not just the one (in this case)
relevant command. This is an obvious privacy leak for the other participants. We currently solve this with
< code class = "docutils literal" > < span class = "pre" > FilteredTransaction< / span > < / code > -s and the use of Merkle Trees. These reveal only the necessary parts of the transaction to the
oracle but still allow it to sign it by providing the Merkle hashes for the remaining parts. See < a class = "reference internal" href = "merkle-trees.html" > < span class = "doc" > Transaction tear-offs< / span > < / a > for
more details.< / p >
2016-11-11 11:52:29 +00:00
< / div >
< div class = "section" id = "pay-per-play-oracles" >
2017-01-06 17:38:23 +00:00
< h3 > Pay-per-play oracles< a class = "headerlink" href = "#pay-per-play-oracles" title = "Permalink to this headline" > ¶< / a > < / h3 >
2016-11-11 11:52:29 +00:00
< p > Because the signature covers the transaction, and transactions may end up being forwarded anywhere, the fact itself
is independently checkable. However, this approach can still be useful when the data itself costs money, because the act
of issuing the signature in the first place can be charged for (e.g. by requiring the submission of a fresh
< code class = "docutils literal" > < span class = "pre" > Cash.State< / span > < / code > that has been re-assigned to a key owned by the oracle service). Because the signature covers the
< em > transaction< / em > and not only the < em > fact< / em > , this allows for a kind of weak pseudo-DRM over data feeds. Whilst a smart
contract could in theory include a transaction parsing and signature checking library, writing a contract in this way
would be conclusive evidence of intent to disobey the rules of the service (< em > res ipsa loquitur< / em > ). In an environment
where parties are legally identifiable, usage of such a contract would by itself be sufficient to trigger some sort of
punishment.< / p >
< / div >
2016-11-29 18:44:59 +00:00
< / div >
< div class = "section" id = "implementing-an-oracle-with-continuously-varying-data" >
2017-01-06 17:38:23 +00:00
< h2 > Implementing an oracle with continuously varying data< a class = "headerlink" href = "#implementing-an-oracle-with-continuously-varying-data" title = "Permalink to this headline" > ¶< / a > < / h2 >
2016-11-29 18:44:59 +00:00
< div class = "section" id = "implement-the-core-classes" >
2017-01-06 17:38:23 +00:00
< h3 > Implement the core classes< a class = "headerlink" href = "#implement-the-core-classes" title = "Permalink to this headline" > ¶< / a > < / h3 >
2016-11-29 18:44:59 +00:00
< p > The key is to implement your oracle in a similar way to the < code class = "docutils literal" > < span class = "pre" > NodeInterestRates.Oracle< / span > < / code > outline we gave above with
both < code class = "docutils literal" > < span class = "pre" > query< / span > < / code > and < code class = "docutils literal" > < span class = "pre" > sign< / span > < / code > methods. Typically you would want one class that encapsulates the parameters to the < code class = "docutils literal" > < span class = "pre" > query< / span > < / code >
method (< code class = "docutils literal" > < span class = "pre" > FixOf< / span > < / code > above), and a < code class = "docutils literal" > < span class = "pre" > CommandData< / span > < / code > implementation (< code class = "docutils literal" > < span class = "pre" > Fix< / span > < / code > above) that encapsulates both an instance of
that parameter class and an instance of whatever the result of the < code class = "docutils literal" > < span class = "pre" > query< / span > < / code > is (< code class = "docutils literal" > < span class = "pre" > BigDecimal< / span > < / code > above).< / p >
< p > The < code class = "docutils literal" > < span class = "pre" > NodeInterestRates.Oracle< / span > < / code > allows querying for multiple < code class = "docutils literal" > < span class = "pre" > Fix< / span > < / code > -es but that is not necessary and is
provided for the convenience of callers who might need multiple and can do it all in one query request. Likewise
the < em > deadline< / em > functionality is optional and can be avoided initially.< / p >
< p > Let’ s see what parameters we pass to the constructor of this oracle.< / p >
< div class = "highlight-kotlin" > < div class = "highlight" > < pre > < span > < / span > < span class = "k" > class< / span > < span class = "nc" > Oracle< / span > < span class = "p" > (< / span > < span class = "k" > val< / span > < span class = "py" > identity< / span > < span class = "p" > :< / span > < span class = "n" > Party< / span > < span class = "p" > ,< / span > < span class = "k" > private< / span > < span class = "k" > val< / span > < span class = "py" > signingKey< / span > < span class = "p" > :< / span > < span class = "n" > KeyPair< / span > < span class = "p" > ,< / span > < span class = "k" > val< / span > < span class = "py" > clock< / span > < span class = "p" > :< / span > < span class = "n" > Clock< / span > < span class = "p" > )< / span > < span class = "p" > =< / span > < span class = "n" > TODO< / span > < span class = "p" > ()< / span >
< / pre > < / div >
< / div >
< p > Here we see the oracle needs to have its own identity, so it can check which transaction commands it is expected to
sign for, and also needs a pair of signing keys with which it signs transactions. The clock is used for the deadline
functionality which we will not discuss further here.< / p >
< p > Assuming you have a data source and can query it, it should be very easy to implement your < code class = "docutils literal" > < span class = "pre" > query< / span > < / code > method and the
parameter and < code class = "docutils literal" > < span class = "pre" > CommandData< / span > < / code > classes.< / p >
< p > Let’ s see how the < code class = "docutils literal" > < span class = "pre" > sign< / span > < / code > method for < code class = "docutils literal" > < span class = "pre" > NodeInterestRates.Oracle< / span > < / code > is written:< / p >
< div class = "highlight-kotlin" > < div class = "highlight" > < pre > < span > < / span > < span class = "k" > fun< / span > < span class = "nf" > sign< / span > < span class = "p" > (< / span > < span class = "n" > ftx< / span > < span class = "p" > :< / span > < span class = "n" > FilteredTransaction< / span > < span class = "p" > ,< / span > < span class = "n" > merkleRoot< / span > < span class = "p" > :< / span > < span class = "n" > SecureHash< / span > < span class = "p" > ):< / span > < span class = "n" > DigitalSignature< / span > < span class = "p" > .< / span > < span class = "n" > LegallyIdentifiable< / span > < span class = "p" > {< / span >
2017-01-03 13:07:48 +00:00
< span class = "k" > if< / span > < span class = "p" > (!< / span > < span class = "n" > ftx< / span > < span class = "p" > .< / span > < span class = "n" > verify< / span > < span class = "p" > (< / span > < span class = "n" > merkleRoot< / span > < span class = "p" > ))< / span > < span class = "p" > {< / span >
2016-11-29 18:44:59 +00:00
< span class = "k" > throw< / span > < span class = "n" > MerkleTreeException< / span > < span class = "p" > (< / span > < span class = "s" > " Rate Fix Oracle: Couldn' t verify partial Merkle tree." < / span > < span class = "p" > )< / span >
< span class = "p" > }< / span >
< span class = "c1" > // Reject if we have something different than only commands.< / span >
< span class = "k" > val< / span > < span class = "py" > leaves< / span > < span class = "p" > =< / span > < span class = "n" > ftx< / span > < span class = "p" > .< / span > < span class = "n" > filteredLeaves< / span >
< span class = "n" > require< / span > < span class = "p" > (< / span > < span class = "n" > leaves< / span > < span class = "p" > .< / span > < span class = "n" > inputs< / span > < span class = "p" > .< / span > < span class = "n" > isEmpty< / span > < span class = "p" > ()< / span > < span class = "p" > & & < / span > < span class = "n" > leaves< / span > < span class = "p" > .< / span > < span class = "n" > outputs< / span > < span class = "p" > .< / span > < span class = "n" > isEmpty< / span > < span class = "p" > ()< / span > < span class = "p" > & & < / span > < span class = "n" > leaves< / span > < span class = "p" > .< / span > < span class = "n" > attachments< / span > < span class = "p" > .< / span > < span class = "n" > isEmpty< / span > < span class = "p" > ())< / span >
< span class = "k" > val< / span > < span class = "py" > fixes< / span > < span class = "p" > :< / span > < span class = "n" > List< / span > < span class = "p" > < < / span > < span class = "n" > Fix< / span > < span class = "p" > > < / span > < span class = "p" > =< / span > < span class = "n" > ftx< / span > < span class = "p" > .< / span > < span class = "n" > filteredLeaves< / span > < span class = "p" > .< / span > < span class = "n" > commands< / span > < span class = "p" > .< / span >
< span class = "n" > filter< / span > < span class = "p" > {< / span > < span class = "n" > identity< / span > < span class = "p" > .< / span > < span class = "n" > owningKey< / span > < span class = "k" > in< / span > < span class = "n" > it< / span > < span class = "p" > .< / span > < span class = "n" > signers< / span > < span class = "p" > & & < / span > < span class = "n" > it< / span > < span class = "p" > .< / span > < span class = "n" > value< / span > < span class = "k" > is< / span > < span class = "n" > Fix< / 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" > value< / span > < span class = "k" > as< / span > < span class = "n" > Fix< / span > < span class = "p" > }< / span >
< span class = "c1" > // Reject signing attempt if we received more commands than we should.< / span >
< span class = "k" > if< / span > < span class = "p" > (< / span > < span class = "n" > fixes< / span > < span class = "p" > .< / span > < span class = "n" > size< / span > < span class = "p" > !=< / span > < span class = "n" > ftx< / span > < span class = "p" > .< / span > < span class = "n" > filteredLeaves< / span > < span class = "p" > .< / span > < span class = "n" > commands< / span > < span class = "p" > .< / span > < span class = "n" > size< / span > < span class = "p" > )< / span >
< span class = "k" > throw< / span > < span class = "n" > IllegalArgumentException< / span > < span class = "p" > ()< / span >
< span class = "c1" > // Reject this signing attempt if there are no commands of the right kind.< / span >
< span class = "k" > if< / span > < span class = "p" > (< / span > < span class = "n" > fixes< / span > < span class = "p" > .< / span > < span class = "n" > isEmpty< / span > < span class = "p" > ())< / span >
< span class = "k" > throw< / span > < span class = "n" > IllegalArgumentException< / span > < span class = "p" > ()< / span >
< span class = "c1" > // For each fix, verify that the data is correct.< / span >
< span class = "k" > val< / span > < span class = "py" > knownFixes< / span > < span class = "p" > =< / span > < span class = "n" > knownFixes< / span > < span class = "c1" > // Snapshot< / span >
< span class = "k" > for< / span > < span class = "p" > (< / span > < span class = "n" > fix< / span > < span class = "k" > in< / span > < span class = "n" > fixes< / span > < span class = "p" > )< / span > < span class = "p" > {< / span >
< span class = "k" > val< / span > < span class = "py" > known< / span > < span class = "p" > =< / span > < span class = "n" > knownFixes< / span > < span class = "p" > [< / span > < span class = "n" > fix< / span > < span class = "p" > .< / span > < span class = "n" > of< / span > < span class = "p" > ]< / span >
< span class = "k" > if< / span > < span class = "p" > (< / span > < span class = "n" > known< / span > < span class = "p" > ==< / span > < span class = "k" > null< / span > < span class = "p" > ||< / span > < span class = "n" > known< / span > < span class = "p" > !=< / span > < span class = "n" > fix< / span > < span class = "p" > )< / span >
< span class = "k" > throw< / span > < span class = "n" > UnknownFix< / span > < span class = "p" > (< / span > < span class = "n" > fix< / span > < span class = "p" > .< / span > < span class = "n" > of< / span > < span class = "p" > )< / span >
< span class = "p" > }< / span >
< span class = "c1" > // It all checks out, so we can return a signature.< / span >
< span class = "c1" > //< / span >
< span class = "c1" > // Note that we will happily sign an invalid transaction, as we are only being presented with a filtered< / span >
< span class = "c1" > // version so we can' t resolve or check it ourselves. However, that doesn' t matter much, as if we sign< / span >
< span class = "c1" > // an invalid transaction the signature is worthless.< / span >
< span class = "k" > return< / span > < span class = "n" > signingKey< / span > < span class = "p" > .< / span > < span class = "n" > signWithECDSA< / span > < span class = "p" > (< / span > < span class = "n" > merkleRoot< / span > < span class = "p" > .< / span > < span class = "n" > bytes< / span > < span class = "p" > ,< / span > < span class = "n" > identity< / span > < span class = "p" > )< / span >
< span class = "p" > }< / span >
< / pre > < / div >
< / div >
< p > Here we can see that there are several steps:< / p >
< ol class = "arabic simple" >
< li > Ensure that the transaction we have been sent is indeed valid and passes verification, even though we cannot see all
of it.< / li >
< li > Check that we only received commands as expected, and each of those commands expects us to sign for them and is of
the expected type (< code class = "docutils literal" > < span class = "pre" > Fix< / span > < / code > here).< / li >
< li > Iterate over each of the commands we identified in the last step and check that the data they represent matches
exactly our data source. The final step, assuming we have got this far, is to generate a signature for the
transaction and return it.< / li >
< / ol >
< / div >
2017-01-06 17:38:23 +00:00
< div class = "section" id = "binding-to-the-network-via-a-cordapp-plugin" >
< h3 > Binding to the network via a CorDapp plugin< a class = "headerlink" href = "#binding-to-the-network-via-a-cordapp-plugin" title = "Permalink to this headline" > ¶< / a > < / h3 >
2016-11-29 18:44:59 +00:00
< div class = "admonition note" >
< p class = "first admonition-title" > Note< / p >
< p class = "last" > Before reading any further, we advise that you understand the concept of flows and how to write them and use
them. See < a class = "reference internal" href = "flow-state-machines.html" > < span class = "doc" > Writing flows< / span > < / a > . Likewise some understanding of Cordapps, plugins and services will be helpful.
2017-01-06 17:38:23 +00:00
See < 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 >
< p > The first step is to create a service to host the oracle on the network. Let’ s see how that’ s implemented:< / p >
< div class = "highlight-kotlin" > < div class = "highlight" > < pre > < span > < / span > class Service(val services: PluginServiceHub) : AcceptsFileUpload, SingletonSerializeAsToken() {
val oracle: Oracle by lazy {
val myNodeInfo = services.myInfo
val myIdentity = myNodeInfo.serviceIdentities(type).first()
val mySigningKey = services.keyManagementService.toKeyPair(myIdentity.owningKey.keys)
Oracle(myIdentity, mySigningKey, services.clock)
}
init {
// Note: access to the singleton oracle property is via the registered SingletonSerializeAsToken Service.
// Otherwise the Kryo serialisation of the call stack in the Quasar Fiber extends to include
// the framework Oracle and the flow will crash.
services.registerFlowInitiator(RatesFixFlow.FixSignFlow::class) { FixSignHandler(it, this) }
services.registerFlowInitiator(RatesFixFlow.FixQueryFlow::class) { FixQueryHandler(it, this) }
}
private class FixSignHandler(val otherParty: Party, val service: Service) : FlowLogic< Unit> () {
@Suspendable
override fun call() {
val request = receive< RatesFixFlow.SignRequest> (otherParty).unwrap { it }
send(otherParty, service.oracle.sign(request.ftx, request.rootHash))
}
}
private class FixQueryHandler(val otherParty: Party, val service: Service) : FlowLogic< Unit> () {
companion object {
object RECEIVED : ProgressTracker.Step(" Received fix request" )
object SENDING : ProgressTracker.Step(" Sending fix response" )
}
override val progressTracker = ProgressTracker(RECEIVED, SENDING)
init {
progressTracker.currentStep = RECEIVED
}
@Suspendable
override fun call(): Unit {
val request = receive< RatesFixFlow.QueryRequest> (otherParty).unwrap { it }
val answers = service.oracle.query(request.queries, request.deadline)
progressTracker.currentStep = SENDING
send(otherParty, answers)
}
}
< / pre > < / div >
< / div >
< p > This may look complicated, but really it’ s made up of some relatively simple elements (in the order they appear in the code):< / p >
< ol class = "arabic simple" >
< li > Accept a < code class = "docutils literal" > < span class = "pre" > PluginServiceHub< / span > < / code > in the constructor. This is your interface to the Corda node.< / li >
< li > Ensure you extend the abstract class < code class = "docutils literal" > < span class = "pre" > SingletonSerializeAsToken< / span > < / code > (see < a class = "reference internal" href = "corda-plugins.html" > < span class = "doc" > The Corda plugin framework< / span > < / a > ).< / li >
< li > Create an instance of your core oracle class that has the < code class = "docutils literal" > < span class = "pre" > query< / span > < / code > and < code class = "docutils literal" > < span class = "pre" > sign< / span > < / code > methods as discussed above.< / li >
< li > Register your client sub-flows (in this case both in < code class = "docutils literal" > < span class = "pre" > RatesFixFlow< / span > < / code > . See the next section) for querying and
signing as initiating your service flows that actually do the querying and signing using your core oracle class instance.< / li >
< li > Implement your service flows that call your core oracle class instance.< / li >
< / ol >
< p > The final step is to register your service with the node via the plugin mechanism. Do this by
implementing a plugin. Don’ t forget the resources file to register it with the < code class = "docutils literal" > < span class = "pre" > ServiceLoader< / span > < / code > framework
(see < a class = "reference internal" href = "corda-plugins.html" > < span class = "doc" > The Corda plugin framework< / span > < / a > ).< / p >
< div class = "highlight-kotlin" > < div class = "highlight" > < pre > < span > < / span > < span class = "k" > class< / span > < span class = "nc" > Plugin< / 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" > val< / span > < span class = "py" > servicePlugins< / span > < span class = "p" > :< / span > < span class = "n" > List< / span > < span class = "p" > < < / span > < span class = "n" > Class< / span > < span class = "p" > < *> > < / span > < span class = "p" > =< / span > < span class = "n" > listOf< / span > < span class = "p" > (< / span > < span class = "n" > Service< / 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 = "p" > }< / span >
< / pre > < / div >
< / div >
< / div >
< div class = "section" id = "providing-client-sub-flows-for-querying-and-signing" >
2017-01-06 17:38:23 +00:00
< h3 > Providing client sub-flows for querying and signing< a class = "headerlink" href = "#providing-client-sub-flows-for-querying-and-signing" title = "Permalink to this headline" > ¶< / a > < / h3 >
2016-11-29 18:44:59 +00:00
< p > We mentioned the client sub-flow briefly above. They are the mechanism that clients, in the form of other flows, will
interact with your oracle. Typically there will be one for querying and one for signing. Let’ s take a look at
those for < code class = "docutils literal" > < span class = "pre" > NodeInterestRates.Oracle< / span > < / code > .< / p >
< div class = "highlight-kotlin" > < div class = "highlight" > < pre > < span > < / span > < span class = "k" > class< / span > < span class = "nc" > FixQueryFlow< / span > < span class = "p" > (< / span > < span class = "k" > val< / span > < span class = "py" > fixOf< / span > < span class = "p" > :< / span > < span class = "n" > FixOf< / span > < span class = "p" > ,< / span > < span class = "k" > val< / span > < span class = "py" > oracle< / span > < span class = "p" > :< / span > < span class = "n" > Party< / span > < span class = "p" > )< / span > < span class = "p" > :< / span > < span class = "n" > FlowLogic< / span > < span class = "p" > < < / span > < span class = "n" > Fix< / span > < span class = "p" > > ()< / span > < span class = "p" > {< / span >
< span class = "n" > @Suspendable< / span >
< span class = "k" > override< / span > < span class = "k" > fun< / span > < span class = "nf" > call< / span > < span class = "p" > ():< / span > < span class = "n" > Fix< / span > < span class = "p" > {< / span >
< span class = "k" > val< / span > < span class = "py" > deadline< / span > < span class = "p" > =< / span > < span class = "n" > suggestInterestRateAnnouncementTimeWindow< / span > < span class = "p" > (< / span > < span class = "n" > fixOf< / span > < span class = "p" > .< / span > < span class = "n" > name< / span > < span class = "p" > ,< / span > < span class = "n" > oracle< / span > < span class = "p" > .< / span > < span class = "n" > name< / span > < span class = "p" > ,< / span > < span class = "n" > fixOf< / span > < span class = "p" > .< / span > < span class = "n" > forDay< / span > < span class = "p" > ).< / span > < span class = "n" > end< / span >
< span class = "c1" > // TODO: add deadline to receive< / span >
< span class = "k" > val< / span > < span class = "py" > resp< / span > < span class = "p" > =< / span > < span class = "n" > sendAndReceive< / span > < span class = "p" > < < / span > < span class = "n" > ArrayList< / span > < span class = "p" > < < / span > < span class = "n" > Fix< / span > < span class = "p" > > > (< / span > < span class = "n" > oracle< / span > < span class = "p" > ,< / span > < span class = "n" > QueryRequest< / span > < span class = "p" > (< / span > < span class = "n" > listOf< / span > < span class = "p" > (< / span > < span class = "n" > fixOf< / span > < span class = "p" > ),< / span > < span class = "n" > deadline< / span > < span class = "p" > ))< / span >
< span class = "k" > return< / span > < span class = "n" > resp< / span > < span class = "p" > .< / span > < span class = "n" > unwrap< / span > < span class = "p" > {< / span >
< span class = "k" > val< / span > < span class = "py" > fix< / span > < span class = "p" > =< / span > < span class = "n" > it< / span > < span class = "p" > .< / span > < span class = "n" > first< / span > < span class = "p" > ()< / span >
< span class = "c1" > // Check the returned fix is for what we asked for.< / span >
< span class = "n" > check< / span > < span class = "p" > (< / span > < span class = "n" > fix< / span > < span class = "p" > .< / span > < span class = "n" > of< / span > < span class = "p" > ==< / span > < span class = "n" > fixOf< / span > < span class = "p" > )< / span >
< span class = "n" > fix< / span >
< span class = "p" > }< / span >
< span class = "p" > }< / span >
< span class = "p" > }< / span >
< span class = "k" > class< / span > < span class = "nc" > FixSignFlow< / span > < span class = "p" > (< / span > < span class = "k" > val< / span > < span class = "py" > tx< / span > < span class = "p" > :< / span > < span class = "n" > TransactionBuilder< / span > < span class = "p" > ,< / span > < span class = "k" > val< / span > < span class = "py" > oracle< / span > < span class = "p" > :< / span > < span class = "n" > Party< / span > < span class = "p" > ,< / span > < span class = "k" > val< / span > < span class = "py" > filterFuns< / span > < span class = "p" > :< / span > < span class = "n" > FilterFuns< / span > < span class = "p" > )< / span > < span class = "p" > :< / span > < span class = "n" > FlowLogic< / span > < span class = "p" > < < / span > < span class = "n" > DigitalSignature< / span > < span class = "p" > .< / span > < span class = "n" > LegallyIdentifiable< / span > < span class = "p" > > ()< / span > < span class = "p" > {< / span >
< span class = "n" > @Suspendable< / span >
< span class = "k" > override< / span > < span class = "k" > fun< / span > < span class = "nf" > call< / span > < span class = "p" > ():< / span > < span class = "n" > DigitalSignature< / span > < span class = "p" > .< / span > < span class = "n" > LegallyIdentifiable< / span > < span class = "p" > {< / span >
< span class = "k" > val< / span > < span class = "py" > wtx< / span > < span class = "p" > =< / span > < span class = "n" > tx< / span > < span class = "p" > .< / span > < span class = "n" > toWireTransaction< / span > < span class = "p" > ()< / span >
< span class = "k" > val< / span > < span class = "py" > partialMerkleTx< / span > < span class = "p" > =< / span > < span class = "n" > FilteredTransaction< / span > < span class = "p" > .< / span > < span class = "n" > buildMerkleTransaction< / span > < span class = "p" > (< / span > < span class = "n" > wtx< / span > < span class = "p" > ,< / span > < span class = "n" > filterFuns< / span > < span class = "p" > )< / span >
< span class = "k" > val< / span > < span class = "py" > rootHash< / span > < span class = "p" > =< / span > < span class = "n" > wtx< / span > < span class = "p" > .< / span > < span class = "n" > id< / span >
< span class = "k" > val< / span > < span class = "py" > resp< / span > < span class = "p" > =< / span > < span class = "n" > sendAndReceive< / span > < span class = "p" > < < / span > < span class = "n" > DigitalSignature< / span > < span class = "p" > .< / span > < span class = "n" > LegallyIdentifiable< / span > < span class = "p" > > (< / span > < span class = "n" > oracle< / span > < span class = "p" > ,< / span > < span class = "n" > SignRequest< / span > < span class = "p" > (< / span > < span class = "n" > rootHash< / span > < span class = "p" > ,< / span > < span class = "n" > partialMerkleTx< / span > < span class = "p" > ))< / span >
< span class = "k" > return< / span > < span class = "n" > resp< / span > < span class = "p" > .< / span > < span class = "n" > unwrap< / span > < span class = "p" > {< / span > < span class = "n" > sig< / span > < span class = "p" > -> < / span >
< span class = "n" > check< / span > < span class = "p" > (< / span > < span class = "n" > sig< / span > < span class = "p" > .< / span > < span class = "n" > signer< / span > < span class = "p" > ==< / span > < span class = "n" > oracle< / span > < span class = "p" > )< / span >
< span class = "n" > tx< / span > < span class = "p" > .< / span > < span class = "n" > checkSignature< / span > < span class = "p" > (< / span > < span class = "n" > sig< / span > < span class = "p" > )< / span >
< span class = "n" > sig< / span >
< span class = "p" > }< / span >
< span class = "p" > }< / span >
< span class = "p" > }< / span >
< / pre > < / div >
< / div >
< p > You’ ll note that the < code class = "docutils literal" > < span class = "pre" > FixSignFlow< / span > < / code > requires a < code class = "docutils literal" > < span class = "pre" > FilterFuns< / span > < / code > instance with the appropriate filter to include only
the < code class = "docutils literal" > < span class = "pre" > Fix< / span > < / code > commands. You can find a further explanation of this in < a class = "reference internal" href = "merkle-trees.html" > < span class = "doc" > Transaction tear-offs< / span > < / a > .< / p >
< / div >
< / div >
< div class = "section" id = "using-an-oracle" >
2017-01-06 17:38:23 +00:00
< h2 > Using an oracle< a class = "headerlink" href = "#using-an-oracle" title = "Permalink to this headline" > ¶< / a > < / h2 >
2016-11-29 18:44:59 +00:00
< p > The oracle is invoked through sub-flows to query for values, add them to the transaction as commands and then get
2017-01-06 17:38:23 +00:00
the transaction signed by the oracle. Following on from the above examples, this is all encapsulated in a sub-flow
2016-11-29 18:44:59 +00:00
called < code class = "docutils literal" > < span class = "pre" > RatesFixFlow< / span > < / code > . Here’ s the < code class = "docutils literal" > < span class = "pre" > call< / span > < / code > method of that flow.< / p >
< div class = "highlight-kotlin" > < div class = "highlight" > < pre > < span > < / span > < span class = "n" > @Suspendable< / span >
< span class = "k" > override< / span > < span class = "k" > fun< / span > < span class = "nf" > call< / span > < span class = "p" > ()< / span > < span class = "p" > {< / span >
< span class = "n" > progressTracker< / span > < span class = "p" > .< / span > < span class = "n" > currentStep< / span > < span class = "p" > =< / span > < span class = "n" > progressTracker< / span > < span class = "p" > .< / span > < span class = "n" > steps< / span > < span class = "p" > [< / span > < span class = "m" > 1< / span > < span class = "p" > ]< / span >
< span class = "k" > val< / span > < span class = "py" > fix< / span > < span class = "p" > =< / span > < span class = "n" > subFlow< / span > < span class = "p" > (< / span > < span class = "n" > FixQueryFlow< / span > < span class = "p" > (< / span > < span class = "n" > fixOf< / span > < span class = "p" > ,< / span > < span class = "n" > oracle< / span > < span class = "p" > ))< / span >
< span class = "n" > progressTracker< / span > < span class = "p" > .< / span > < span class = "n" > currentStep< / span > < span class = "p" > =< / span > < span class = "n" > WORKING< / span >
< span class = "n" > checkFixIsNearExpected< / span > < span class = "p" > (< / span > < span class = "n" > fix< / span > < span class = "p" > )< / span >
< span class = "n" > tx< / span > < span class = "p" > .< / span > < span class = "n" > addCommand< / span > < span class = "p" > (< / span > < span class = "n" > fix< / span > < span class = "p" > ,< / span > < span class = "n" > oracle< / span > < span class = "p" > .< / span > < span class = "n" > owningKey< / span > < span class = "p" > )< / span >
< span class = "n" > beforeSigning< / span > < span class = "p" > (< / span > < span class = "n" > fix< / span > < span class = "p" > )< / span >
< span class = "n" > progressTracker< / span > < span class = "p" > .< / span > < span class = "n" > currentStep< / span > < span class = "p" > =< / span > < span class = "n" > SIGNING< / span >
< span class = "k" > val< / span > < span class = "py" > signature< / span > < span class = "p" > =< / span > < span class = "n" > subFlow< / span > < span class = "p" > (< / span > < span class = "n" > FixSignFlow< / span > < span class = "p" > (< / span > < span class = "n" > tx< / span > < span class = "p" > ,< / span > < span class = "n" > oracle< / span > < span class = "p" > ,< / span > < span class = "n" > filterFuns< / span > < span class = "p" > ))< / span >
< span class = "n" > tx< / span > < span class = "p" > .< / span > < span class = "n" > addSignatureUnchecked< / span > < span class = "p" > (< / span > < span class = "n" > signature< / span > < span class = "p" > )< / span >
< span class = "p" > }< / span >
< / pre > < / div >
< / div >
< p > As you can see, this:< / p >
< ol class = "arabic simple" >
< li > Queries the oracle for the fact using the client sub-flow for querying from above.< / li >
< li > Does some quick validation.< / li >
< li > Adds the command to the transaction containing the fact to be signed for by the oracle.< / li >
< li > Calls an extension point that allows clients to generate output states based on the fact from the oracle.< / li >
< li > Requests the signature from the oracle using the client sub-flow for signing from above.< / li >
< li > Adds the signature returned from the oracle.< / li >
< / ol >
< p > Here’ s an example of it in action from < code class = "docutils literal" > < span class = "pre" > FixingFlow.Fixer< / span > < / code > .< / p >
< div class = "highlight-kotlin" > < div class = "highlight" > < pre > < span > < / span > fun filterCommands(c: Command) = oracleParty.owningKey in c.signers & & c.value is Fix
2017-01-03 13:07:48 +00:00
2016-11-29 18:44:59 +00:00
val filterFuns = FilterFuns(filterCommands = ::filterCommands)
val addFixing = object : RatesFixFlow(ptx, filterFuns, oracleParty, fixOf, BigDecimal.ZERO, BigDecimal.ONE) {
@Suspendable
override fun beforeSigning(fix: Fix) {
newDeal.generateFix(ptx, StateAndRef(txState, handshake.payload.ref), fix)
// And add a request for timestamping: it may be that none of the contracts need this! But it can' t hurt
// to have one.
ptx.setTime(serviceHub.clock.instant(), 30.seconds)
}
}
subFlow(addFixing)
< / pre > < / div >
< / div >
2017-01-06 17:38:23 +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" >
< a href = "tutorial-attachments.html" class = "btn btn-neutral float-right" title = "Using attachments" accesskey = "n" > Next < span class = "fa fa-arrow-circle-right" > < / span > < / a >
2016-11-29 18:44:59 +00:00
< a href = "using-a-notary.html" class = "btn btn-neutral" title = "Using a notary service" 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 >